poj 2965 The Pilots Brothers' refrigerator枚举(bfs+位运算)

时间:2021-06-01 07:36:40
//题目:http://poj.org/problem?id=2965
//题意:电冰箱有16个把手,每个把手两种状态(开‘-’或关‘+’),只有在所有把手都打开时,门才开,输入数据是个4*4的矩阵,因此考虑用位表示。可以改变任
意一个把手的位置,但同时改变其所在的行和列。求最小步骤.
//耗时 800MS
1 #include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<queue> using namespace std;
int id,vis[<<];
int a[<<],b[<<],before[<<];
int p[]={, , , , , , , , , ,
, , , , , };
struct node
{
int x,step;
}; void hui(int x)
{
if(x!=id)
{
hui(before[x]);
printf("%d %d\n",a[x],b[x]);
}
}; void bfs()
{
queue<node>q;
int i;
struct node cur,next;
next.step=; next.x=id;
q.push(next);
memset(vis,,sizeof(vis));
vis[next.x]=; while(!q.empty())
{
cur=q.front();
q.pop();
for(i=; i<; i++)
{
next.x=cur.x^p[i];
next.step=cur.step+; if(vis[next.x]==)
{
before[next.x]=cur.x;
a[next.x]=-(i/);
b[next.x]=-(i%); vis[next.x]=;
q.push(next);
if(next.x==)
{
printf("%d\n",next.step);
hui(next.x);
}
}
}
}
}; int main()
{
int i,j;
char c;
id=;
for(i=; i<; i++)
{
for(j=; j<; j++)
{
id<<=;
scanf("%c",&c);
if(c=='+')
id+=;
}
getchar();
}
bfs();
return ;
}

bfs用 before数组 来回溯改变的点的坐标。

不过耗时太多,这题用 dfs更好,因为要求输出翻转过程。

DFS可以看一下:http://blog.csdn.net/lyy289065406/article/details/6642597这个博客代码跑时较少