poj 2965 The Pilots Brothers' refrigerator

//参照 poj8 1753 Flip Game
#include<iostream> //bfs+位运算
#include <stdio.h>

#include <stack>
using namespace std;
const int mod=0x55555555; //mod=(0101 0101 0101 0101 0101 0101 0101 0101)十六进制,实际上是16,4*4个 01
int fac[4][4]={{1,4,16,64},{256,1024,4096,16384},{65536,262144,1048576,4194304},{16777216,67108864,268435456,1073741824}};

const int inf=1<<16;
int q[inf],dis[inf],fa[inf],pos[inf];
bool vis[mod]; //int 会超数组的总大小限制

int main()
{
int num=0;
char ch[5];
for(int i=0;i<4;++i)
{
scanf("%s",ch);
for(int j=0;j<4;++j)
if(ch[j]=='+')
num+=fac[i][j];
}
q[0]=num;
vis[num]=true;
dis[0]=0;
int front=0,rear=1;
while(front<rear)
{
if(q[front]==0)
{
printf("%d\n",dis[front]);
stack<int> path;
int r=front;
while(r>0) //r=0表示起点
{

path.push(pos[r]);
r=fa[r];
}
while(!path.empty())
{
int p=path.top();
printf("%d %d\n",p/4+1,p%4+1);
path.pop();
}
break;
}
for(int i=0;i<4;++i)
for(int j=0;j<4;++j) //翻转棋子[i][j]
{

int t=q[front];
for(int k=0;k<4;++k)
{
t+=fac[k][j]; t=t&mod;
t+=fac[i][k]; t=t&mod;
}
t+=fac[i][j]; t=t&mod;
if(vis[t])
continue;
vis[t]=true;
dis[rear]=dis[front]+1;
fa[rear]=front;
pos[rear]=i*4+j;
q[rear++]=t;
}
front++;
}
return 0;
}

 

 

 

枚举
//每一个点(i,j)最多做一次翻转,因为翻转两次相当于没有翻转
//所以结果可以转化为一个只包含0、1的十六位数组,(1表示翻转)
//枚举所有的可能性组合,逐个检验,取包含1最少的串 for(i=1;i<(1<<16);++i)

#include<iostream> //枚举,时间 922MS 险过
using namespace std;
int table[4][4],tmp[4][4],i,j,k;
char ch[4][5];
int main()
{
int c,num,inf=20,p[16],res[16];
for(i=0;i<4;++i)
scanf("%s",ch[i]);
for(i=0;i<4;++i)
for(j=0;j<4;++j)
if(ch[i][j]=='-')
table[i][j]=1;
for(i=1;i<(1<<16);++i)
{
j=i;
c=0;num=0;
while(j)
{
p[c++]=j%2;
num+=j%2;
j/=2;
}
if(num>=inf) //剪枝,如果某一数字所包含1的个数大于inf则不必讨论下去
continue;
for(j=0;j<4;++j)
for(k=0;k<4;++k)
tmp[j][k]=table[j][k];
for(j=0;j<c;++j)
{
if(p[j]==0)
continue;
int a=j/4,b=j%4;
for(k=0;k<4;++k)
tmp[k][b]=(tmp[k][b]+1)%2,tmp[a][k]=(tmp[a][k]+1)%2;
tmp[a][b]=(tmp[a][b]+1)%2;
}
int tag=1;
for(j=0;j<4&&tag;++j)
for(k=0;k<4&&tag;++k)
if(tmp[j][k]==0)
tag=0;
if(tag)
{
inf=num;
for(j=0;j<16;++j)
res[j]=p[j];
}
}

printf("%d\n",inf);
for(i=0;i<16;++i)
if(res[i]==1)
{
printf("%d %d\n",i/4+1,i%4+1);
}
return 0;
}



posted on 2011-07-06 11:11  sysu_mjc  阅读(152)  评论(0编辑  收藏  举报

导航