给出一个16个点所构成的图形,分别由0,1组成,每次操作可以任选其中相连的两个点(必须一个为0,一个为1),进行0,1,交换
问3步内是否可以把图形变成:0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1状态
若不行,输出more
状压存储图形状态。ida*搜索 或者 BFS都行
IDA*搜索
#include "stdio.h"
#include "string.h"
const int b[]={0,1,2,4,8,16,32,64,128,256,512,1024,2048,4096,8192,16384,32768,65536};
const int adj[17][5]=
{
{0,0,0,0,0},
{0,2,3,5,9}, //1
{0,1,4,6,10}, //2
{0,1,4,7,11}, //3
{0,2,3,8,12}, //4
{0,1,6,7,13}, //5
{0,2,5,8,14}, //6
{0,3,5,8,15}, //7
{0,4,6,7,16}, //8
{0,1,10,11,13}, //9
{0,2,9,12,14}, //10
{0,3,9,12,15}, //11
{0,4,10,11,16}, //12
{0,5,9,14,15}, //13
{0,6,10,13,16}, //14
{0,7,11,13,16}, //15
{0,8,12,14,15} //16
};
int ans,flag,aim;
int mark[70010];
int cal(int x)
{
int i,cnt;
cnt=0;
for (i=1;i<=8;i++)
if ((x&b[i])!=0)
cnt++;
return cnt;
}
void dfs(int cur,int n)
{
int next,x,cnt,i,j;
if (cur==aim)
{
flag=1;
return ;
}
if (flag==1)
return ;
cnt=0;
for (i=1;i<=8;i++)
if ((cur&b[i])!=0) cnt++;
if (n+cnt>ans)
return ;
for (i=1;i<=16;i++)
{
x=cur&b[i];
if (x!=0)
for (j=1;j<=4;j++)
{
x=cur&b[adj[i][j]];
if (x==0)
{
next=cur;
next^=b[i];
next^=b[adj[i][j]];
if (mark[next]==0)
{
mark[next]=1;
dfs(next,n+1);
mark[next]=0;
}
}
}
}
}
int main()
{
int t,Case,i,status,cnt,x;
scanf("%d",&t);
Case=1;
memset(mark,0,sizeof(mark));
while (t--)
{
status=aim=cnt=0;
for (i=1;i<=16;i++)
{
scanf("%d",&x);
if (i<=8) cnt+=x;
status+=x*b[i];
}
for (i=9;i<=16;i++)
aim+=b[i];
printf("Case #%d: ",Case++);
if (aim==status)
{
printf("0\n");
continue;
}
if (cnt>3)
{
printf("more\n");
continue;
}
ans=0;
while(1)
{
ans++;
flag=0;
if (ans==4) break;
mark[status]=1;
dfs(status,0);
mark[status]=0;
if (flag==1)
break;
}
if (ans==4)
printf("more\n");
else
printf("%d\n",ans);
}
return 0;
}
BFS
#include "stdio.h"
#include "string.h"
#include "queue"
using namespace std;
const int b[]={0,1,2,4,8,16,32,64,128,256,512,1024,2048,4096,8192,16384,32768,65536};
const int adj[17][5]=
{
{0,0,0,0,0},
{0,2,3,5,9}, //1
{0,1,4,6,10}, //2
{0,1,4,7,11}, //3
{0,2,3,8,12}, //4
{0,1,6,7,13}, //5
{0,2,5,8,14}, //6
{0,3,5,8,15}, //7
{0,4,6,7,16}, //8
{0,1,10,11,13}, //9
{0,2,9,12,14}, //10
{0,3,9,12,15}, //11
{0,4,10,11,16}, //12
{0,5,9,14,15}, //13
{0,6,10,13,16}, //14
{0,7,11,13,16}, //15
{0,8,12,14,15} //16
};
int ans,flag,aim;
int mark[70010];
int cal(int x)
{
int i,cnt;
cnt=0;
for (i=1;i<=8;i++)
if ((x&b[i])!=0) cnt++;
return cnt;
}
int bfs(int cur)
{
int i,j,next;
queue<int>q;
q.push(cur);
memset(mark,-1,sizeof(mark));
mark[cur]=0;
while (!q.empty())
{
cur=q.front();
q.pop();
if (mark[cur]==3) continue;
for (i=1;i<=16;i++)
if ((cur&b[i])!=0)
for (j=1;j<=4;j++)
if ((cur&b[adj[i][j]])==0)
{
next=cur;
next^=b[i];
next^=b[adj[i][j]];
if (mark[next]==-1 && cal(next)+mark[cur]<=3)
{
mark[next]=mark[cur]+1;
if (next==aim) return mark[next];
q.push(next);
}
}
}
return -1;
}
int main()
{
int t,Case,i,status,cnt,x;
scanf("%d",&t);
Case=1;
aim=0;
for (i=9;i<=16;i++)
aim+=b[i];
while (t--)
{
status=cnt=0;
for (i=1;i<=16;i++)
{
scanf("%d",&x);
if (i<=8) cnt+=x;
status+=x*b[i];
}
printf("Case #%d: ",Case++);
if (aim==status)
{
printf("0\n");
continue;
}
if (cnt>3)
{
printf("more\n");
continue;
}
ans=bfs(status);
if (ans==-1)
printf("more\n");
else
printf("%d\n",ans);
}
return 0;
}