Continuous Same Game (2)是个很BT的搜索,这题是为了做(2)才来做一下的。其实直接模拟很easy的,纯属无聊写了个位运算版本的,感觉效率似乎差不多。。就是用3位表示每一位的状态,这样一个longlong就可以存下一列的状态。
1 #include <stdio.h> 2 #include <string.h> 3 #include <stdlib.h> 4 typedef long long LL; 5 LL d[22],nfull[22],full[22]; 6 int di[]={-1,1,0,0},dj[]={0,0,1,-1},ds[]={-3,3,0,0},vis[22]; 7 char str[22]; 8 int n,m,can,bi,bj,bans,scr; 9 int canmove(int i,int j,int c){ 10 return i>=0&&j>=0&&i<n&&j<m&&(c||0==((vis[j]>>i)&1)); 11 } 12 int dfs(int i,int j,LL stat,int c){ 13 if((d[j]&nfull[i])^stat)return 0; 14 int now=1;vis[j]|=(1<<i); 15 if(c)d[j]|=nfull[i]; 16 for(int k=0;k<4;k++) 17 if(canmove(i+di[k],j+dj[k],c)) 18 now+=dfs(i+di[k],j+dj[k],k?(stat<<ds[k]):(stat>>3),c); 19 return now; 20 } 21 void clear(){ 22 for(int j=0,k=0;j<m;j++){ 23 for(int i=0,now=0;i<n;i++){ 24 LL stat=d[j]&nfull[now]; 25 if(stat==nfull[now])d[j]=((d[j]&full[now])|((d[j]&~full[now+1])>>3)); 26 else if(stat==0)break; 27 else now++; 28 } 29 if(d[j]!=0){ 30 d[k++]=d[j]; 31 if(k!=j+1)d[j]=0; 32 } 33 } 34 } 35 void init(){ 36 for(int i=0;i<20;i++)nfull[i]=(7LL<<(3*i)); 37 for(int i=0;i<20;i++)full[i]=(1LL<<(3*i))-1; 38 } 39 int main(){ 40 //freopen("test.in","r",stdin); 41 init(); 42 while(scanf("%d%d",&n,&m)!=EOF){ 43 memset(d,0,sizeof d); 44 for(int i=n-1;i>=0;i--){ 45 scanf("%s",str); 46 for(int j=0;j<m;j++)d[j]|=((LL)(str[j]-'0')<<(3*i)); 47 } 48 can=1,scr=0; 49 for(;;){ 50 bans=0; 51 memset(vis,0,sizeof vis); 52 for(int i=n-1;i>=0;i--)for(int j=0;j<m;j++) 53 if(((vis[j]>>i)&1)==0&&(d[j]&nfull[i])&&((d[j]&nfull[i])!=nfull[i])){ 54 int tmp=dfs(i,j,d[j]&nfull[i],0); 55 if(tmp>bans)bans=tmp,bi=i,bj=j; 56 57 } 58 if(bans<=1)break; 59 scr+=bans*(bans-1); 60 dfs(bi,bj,d[bj]&nfull[bi],1); 61 clear(); 62 } 63 printf("%d\n",scr); 64 } 65 }