LOJ #2471. 「九省联考 2018」一双木棋 记忆化搜索

简单记忆化搜索. 

显然,数字的形态是类似阶梯下降的,状态数不会太多,记忆化爆搜就行. 

code: 

#include <bits/stdc++.h>      
#define N 12       
#define mod 1000000007       
#define base 12
#define ll long long  
#define inf 1000000000 
#define setIO(s) freopen(s".in","r",stdin) 
using namespace std;                 
map<ll,int>vis;    
map<ll,int>fin;    
int n,m; 
int cur[12],A[12][12],B[12][12];                       
ll ha() 
{     
	ll an=1;  
	for(int i=1;i<=n;++i)   
	{
		if(!cur[i])   
			break;   
		an=an*base+cur[i];      
	}
	return an;  
}                
// 非 - 黑 - A 
// 牛 - 白 - B   
// d=1:非走;d=0 : 牛走   
// d=1:  f[now]=max(f[now],a[选]+f[now+a]);    
// d=0:  f[now]=min(f[now],-b[选]+f[now+a]);        
int solve(int d) 
{
	ll cu=ha();   
	if(vis[cu])      
		return fin[cu];                   
	vis[cu]=1;  
	int tmp=(d==1?-inf:inf);  
	for(int i=1;i<=n;++i) 
	{
		if(cur[i]<cur[i-1])   
		{      
			++cur[i];   
			if(d==1)  
			    tmp=max(tmp,A[i][cur[i]]+solve(d^1));   
			else 
				tmp=min(tmp,-B[i][cur[i]]+solve(d^1));     
			--cur[i];  
		}
	}
	fin[cu]=tmp;  
	return tmp;  
}
int main() 
{ 
	// setIO("input");  
	int i,j;           
	scanf("%d%d",&n,&m);     
	for(i=1;i<=n;++i)            
		for(j=1;j<=m;++j)   
			scanf("%d",&A[i][j]);  
	for(i=1;i<=n;++i) 
		for(j=1;j<=m;++j)   
			scanf("%d",&B[i][j]);   
	cur[0]=m;     
	for(i=1;i<=n;++i)             
		cur[i]=m;         
	ll c=ha();        
	vis[c]=1;   
	fin[c]=0;     
	for(i=1;i<=n;++i)   
		cur[i]=0; 
	printf("%d\n",solve(1));  
	return 0; 
}

  

posted @ 2020-03-09 22:19  EM-LGH  阅读(172)  评论(0编辑  收藏  举报