有了之前的基础,3进制DP根本不在话下啊,半个小时就搞定了(本来就是水题好不好)
极大极小过程+记忆化搜索
话说第一次接触博弈论,还有点紧张(紧张个P啊连Alpha-Beta剪枝都没有的水题)
然后大概看了下极大极小过程,发现这题根本用不到什么啊TAT
顺便吐槽数据好水63MS就过了,竟然rank27,不科学。
#include<iostream> #include<cstdio> #include<cstring> using namespace std; const int N=1024*1024+5; const int inf=1e9; char mp[10][10]; int f[N],x[12],y[12],bin[30],tot,n; bool vis[N],tra[10][10]; int dx[4]={0,0,1,-1}; int dy[4]={1,-1,0,0}; int get(int s,int pos){ if(s&bin[pos<<1])return 1; if(s&bin[pos*2-1])return 2; return 0; } int put(int x,int pos){ switch(x){ case 0:return 0; case 1:return bin[pos<<1]; case 2:return bin[2*pos-1]; } } void print(int s){ for(int i=1;i<=tot;i++) printf("%d",get(s,i)-1);putchar('\n'); } int dfs(int x,int y){ if(tra[x][y])return 0; int ans=1;tra[x][y]=1; for(int i=0;i<4;i++){ int tx=x+dx[i],ty=y+dy[i]; if(tx<1||tx>n||ty<1||ty>n||tra[tx][ty]||mp[tx][ty]!=mp[x][y])continue; ans+=dfs(tx,ty); } return ans; } int calc(int s){ for(int i=1;i<=tot;i++){ int t=get(s,i); if(t==1)mp[x[i]][y[i]]='0'; else mp[x[i]][y[i]]='1'; } memset(tra,0,sizeof(tra)); int sum0=0,sum1=0; for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) if(mp[i][j]=='0')sum0=max(sum0,dfs(i,j)); else sum1=max(sum1,dfs(i,j)); return sum0-sum1; } int dfs(int s,int p,int step){ if(vis[s])return f[s]; vis[s]=true; if(!step)return f[s]=calc(s); f[s]=p?inf:-inf; for(int i=1;i<=tot;i++) if(!get(s,i)){ if(p)f[s]=min(f[s],dfs(s|put(p+1,i),p^1,step-1)); else f[s]=max(f[s],dfs(s|put(p+1,i),p^1,step-1)); } return f[s]; } int main(){ //freopen("a.in","r",stdin); bin[1]=1; for(int i=2;i<=24;i++)bin[i]=bin[i-1]<<1; while(scanf("%d",&n)&&n){ tot=0;int sum=0; for(int i=1;i<=n;i++){ scanf("%s",mp[i]+1); for(int j=1;j<=n;j++) if(mp[i][j]=='.')x[++tot]=i,y[tot]=j; else sum++; } memset(vis,0,sizeof(vis)); int ans=dfs(0,sum&1,tot); for(int i=1;i<=tot;i++) if(f[put((sum&1)+1,i)]==ans){ if(sum&1)ans*=-1; printf("(%d,%d) %d\n",x[i]-1,y[i]-1,ans); break; } } return 0; }