[ZOJ 3353] Chess Board [搜索+状态压缩]

来源:互联网 发布:2016世界网络大会 编辑:程序博客网 时间:2024/05/16 11:05

给定一个布满黑白棋的棋盘,你有四种翻法可以选,一旦选了一种翻法,在当局游戏中就只能使用这种翻法。某种翻法是指,当你翻某个棋子时,其上下左右多少个也会一起跟着翻面。问能否翻成全白,翻成全白所需要的最少步数以及所选的翻法。若多种翻法都可达到最小步数,优先使用编号小的翻法。

数据范围:15*15的棋盘,四种翻法在题面里给出,与输入无关。

对于第一种翻法,如果确定了第一排15个的情况,即翻或不翻,为了把第一排清成全白,就能知道第二排的15个的情况,以此类推就可以推到最后一排。所以枚举第一排的15个翻的情况即可。

对于剩下三种同理,枚举最后一列/第一列翻的情况即可。

代码写的可搓了...

#include <cstdio>#include <cstring>#include <algorithm>using namespace std;int n,m,nn,mm,ans,anskind;bool a[15][15],d[15][15];int b[15],c[16];inline void update(int &a,int b) {if (b!=-1&&(a==-1||a>b)) a=b;}inline int nbits(int x) {int ans=0;while (x) {ans+=x&1;x>>=1;}return ans;}void bitprint(int x) {while (x) {printf("%d",x&1);x>>=1;}printf("\n");}int try1(int o) {int ans=nbits(o);c[0]^=o;c[0]^=o<<1&mm;c[0]^=o>>1;c[1]^=o;for (int i=1;i<n;i++) {int tmp=c[i-1];ans+=nbits(tmp);c[i]^=tmp;c[i]^=tmp<<1&mm;c[i]^=tmp>>1;c[i+1]^=tmp;}if (c[n-1]) return -1;return ans;}int try2(int o) {int ans=nbits(o);c[0]^=o;c[0]^=o<<1&mm;c[1]^=o<<1&mm;c[1]^=o>>1;c[1]^=o;for (int i=1;i<n;i++) {int tmp=c[i-1];ans+=nbits(tmp);c[i]^=tmp;c[i]^=tmp<<1&mm;c[i+1]^=tmp<<1&mm;c[i+1]^=tmp>>1;c[i+1]^=tmp;}if (c[n-1]) return -1;return ans;}int try3(int o) {int ans=nbits(o);c[0]^=o;c[0]^=o<<1&mm;c[0]^=o>>1;c[1]^=o<<1&mm;c[1]^=o;for (int i=1;i<n;i++) {int tmp=c[i-1];ans+=nbits(tmp);c[i]^=tmp;c[i]^=tmp<<1&mm;c[i]^=tmp>>1;c[i+1]^=tmp<<1&mm;c[i+1]^=tmp;}if (c[n-1]) return -1;return ans;}int try4(int o) {int ans=nbits(o);c[0]^=o;c[0]^=o<<1&mm;c[0]^=o>>1;c[1]^=o<<1&mm;c[1]^=o>>1;for (int i=1;i<n;i++) {int tmp=c[i-1];ans+=nbits(tmp);c[i]^=tmp;c[i]^=tmp<<1&mm;c[i]^=tmp>>1;c[i+1]^=tmp<<1&mm;c[i+1]^=tmp>>1;}if (c[n-1]) return -1;return ans;}void getb() {int i,j;for (i=0;i<n;i++) {int tmp=0;for (j=0;j<m;j++) {tmp<<=1;tmp|=a[i][j];}b[i]=tmp;}}void flip1() {int i,j,o,oldans=ans;getb();for (o=0;o<=mm;o++) {memcpy(c,b,sizeof(b));update(ans,try1(o));}if (oldans!=ans) anskind=1;}void flip2() {int i,j,o,oldans=ans;getb();for (o=0;o<=mm;o++) {memcpy(c,b,sizeof(b));update(ans,try2(o));}if (oldans!=ans) anskind=2;}void flip3() {int i,j,o,oldans=ans;getb();for (o=0;o<=mm;o++) {memcpy(c,b,sizeof(b));update(ans,try3(o));}if (oldans!=ans) anskind=3;}void flip4() {int i,j,o,oldans=ans;getb();for (o=0;o<=mm;o++) {memcpy(c,b,sizeof(b));update(ans,try4(o));}if (oldans!=ans) anskind=4;}int main() {int i,j;while (scanf("%d%d",&n,&m),n!=0) {nn=(1<<n)-1;mm=(1<<m)-1;for (i=0;i<n;i++)for (j=0;j<m;j++) {char c;scanf(" %c",&c);a[i][j]=(c=='1');}ans=-1;anskind=-1;flip1();for (i=0;i<n;i++)for (j=0;j<m;j++) d[m-j-1][i]=a[i][j];swap(n,m);nn=(1<<n)-1;mm=(1<<m)-1;for (i=0;i<n;i++)for (j=0;j<m;j++)a[i][j]=d[i][j];flip2();for (i=0;i+i<n;i++)for (j=0;j<m;j++)swap(a[i][j],a[n-i-1][j]);flip3();flip4();if (ans!=-1) printf("%d %d\n",anskind,ans);else printf("Impossible\n");}return 0;}


0 0