poj 3317 Stake Your Claim 极大极小搜索
思路:为了方便,当c1>c2时将0变为1,1变为0.
空格最多有10个,每个空格有3个状态,如果不状态压缩,会TLE的。所以最多有3^10种情况
代码如下:
1 #include<iostream> 2 #include<stdio.h> 3 #include<algorithm> 4 #include<iomanip> 5 #include<cmath> 6 #include<cstring> 7 #include<vector> 8 #include<map> 9 #define inf 1<<30 10 using namespace std; 11 struct point 12 { 13 int x,y; 14 point(){} 15 point(int _x,int _y):x(_x),y(_y){} 16 }pos[11],s; 17 int move[4][2]={{-1,0},{1,0},{0,-1},{0,1}}; 18 char str[9][10]; 19 int x,y,n,sum,ret,dp[60000],p[15]; 20 map<int ,int>mm; 21 bool vis[9][9]; 22 void dfs(int x,int y) 23 { 24 if(vis[x][y]) return ; 25 vis[x][y]=1; 26 sum++; 27 for(int i=0;i<4;i++){ 28 int a=x+move[i][0]; 29 int b=y+move[i][1]; 30 if(a>=0&&a<n&&b>=0&&b<n&&!vis[a][b]&&str[x][y]==str[a][b]) 31 dfs(a,b); 32 } 33 } 34 int get_score() 35 { 36 memset(vis,0,sizeof(vis)); 37 int t1=0,t2=0; 38 for(int i=0;i<n;i++) 39 for(int j=0;j<n;j++){ 40 if(!vis[i][j]){ 41 sum=0; 42 dfs(i,j); 43 if(str[i][j]=='0') t1=max(t1,sum); 44 else t2=max(t2,sum); 45 } 46 } 47 return t1-t2; 48 } 49 int minimax(int ,int ,int ,int); 50 int maxmini(int state,int now,int d,int mi) 51 { 52 if(!state) return get_score(); 53 if(dp[now]!=-inf) return dp[now]; 54 int ma=-inf,st=state,k,j; 55 while(st){ //枚举所有的1的情况,也就是'.'的情况 56 k=st&(-st); // 找到st倒数第一个1 57 j=mm[k]; //1的位置 58 str[pos[j].x][pos[j].y]='0'; 59 int t=minimax(state-k,now+p[j],d+1,ma); 60 str[pos[j].x][pos[j].y]='.'; 61 ma=max(ma,t); 62 if(ma>=mi) return ma; 63 if(d==0){ //更新结果 64 if(ret<ma||(ret==ma&&(s.x>pos[j].x||(s.x==pos[j].x&&s.y>pos[j].y)))){ 65 s=pos[j]; 66 ret=ma; 67 } 68 } 69 st-=k; //继续枚举下一个1 70 } 71 return dp[now]=ma; 72 } 73 int minimax(int state,int now,int d,int ma) 74 { 75 if(!state) return get_score(); 76 if(dp[now]!=-inf) return dp[now]; 77 int mi=inf,k,st=state,j; 78 while(st){ 79 k=st&(-st); 80 j=mm[k]; 81 str[pos[j].x][pos[j].y]='1'; 82 int t=maxmini(state-k,now+2*p[j],d+1,mi); 83 str[pos[j].x][pos[j].y]='.'; 84 mi=min(mi,t); 85 if(mi<=ma) return mi; 86 st-=k; 87 } 88 return dp[now]=mi; 89 } 90 int main() 91 { 92 // freopen("1.txt","r",stdin); 93 p[0]=1; 94 for(int i=1;i<=10;i++) p[i]=3*p[i-1]; 95 for(int i=0;i<=11;i++) mm[(1<<i)]=i; 96 while(scanf("%d",&n)&&n){ 97 int c1=0,c2=0,num=0; 98 for(int i=0;i<n;i++){ 99 scanf("%s",str[i]); 100 for(int j=0;j<n;j++){ 101 if(str[i][j]=='0') c1++; 102 else if(str[i][j]=='1') c2++; 103 else pos[num++]=point(i,j); 104 } 105 } 106 if(c1>c2){ //始终让0先走 107 for(int i=0;i<n;i++) 108 for(int j=0;j<n;j++){ 109 if(str[i][j]=='0') str[i][j]='1'; 110 else if(str[i][j]=='1') str[i][j]='0'; 111 } 112 } 113 for(int i=0;i<p[num];i++) dp[i]=-inf; 114 ret=-inf; 115 maxmini((1<<num)-1,0,0,inf); 116 printf("(%d,%d) %d\n",s.x,s.y,ret); 117 } 118 return 0; 119 }