题目大意:
Black有一个Villa,有好多房间。房间里的开关经常控制其他房间的灯。Black不敢进到没开灯的房间,所以他需要
一步步打开房间的灯,直到回到卧室,同时必须把其他房间的灯关掉。
输入:r,房间个数
d,房间之间的门的数量。s,开关数量
接下来d行,输入i和j,表示i有一扇门通往j
接下来s行,输入k和l,表示k房间的开关控制房间l
解题思路:
BFS搜索问题
代码如下:
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <string>
#include <queue>
#include <algorithm>
using namespace std;
#define maxn 15
#define maxs 20010
#define MOVETO 20
#define SWITCHON 10
#define SWITCHOFF 0
int r;
int control[maxs];
int op[maxs];
bool visited[maxs];
bool g[maxn][maxn], light[maxn][maxn];
bool init()
{
int t1, t2, d, s;
scanf("%d%d%d", &r, &d, &s);
if (r==0) return false;
memset(g, false, sizeof(g));
for (int i=0; i<d; i++)
{
scanf("%d%d", &t1, &t2);
t1--; t2--;
g[t1][t2]=g[t2][t1]=true;
}
memset(light, false, sizeof(light));
for (int i=0; i<s; i++)
{
scanf("%d%d", &t1, &t2);
t1--; t2--;
light[t1][t2]=true;
}
return true;
}
bool checkstay(int u)
{
int pos=u%16;
int tmp=u/16;
int j=1<<pos;
if (tmp&j) return true;
return false;
}
int bfs()
{
queue<int> q;
queue<int> step;
int target =(1<<(r+4-1))+r-1;
int u=(1<<4), k=0;
int u_new, uu, pos;
memset(visited, 0, sizeof(visited));
memset(control, 255, sizeof(control));
visited[u]=true;
q.push(u);
step.push(k);
while (!q.empty())
{
u=q.front(); q.pop();
k=step.front(); step.pop();
pos=u%16; uu=u>>4;
if (u==target){return k;}
for (int i=0; i<r; i++)
{
if (g[pos][i])
{
u_new=u-pos+i;
if (!visited[u_new] && checkstay(u_new))
{
q.push(u_new); step.push(k+1); visited[u_new]=true;
control[u_new]=u;
op[u_new]=MOVETO+i;
}
}
}
for (int i=0, j=(1<<4); i<r; i++, j=j<<1, uu=uu>>1)
if (light[pos][i])
{
if (uu&1)
{
u_new=u-j;
if (!visited[u_new] && checkstay(u_new))
{
q.push(u_new); step.push(k+1); visited[u_new]=true;
control[u_new]=u;
op[u_new]=SWITCHOFF+i;
}
}
else
{
u_new=u+j;
if (!visited[u_new] && checkstay(u_new))
{
q.push(u_new); step.push(k+1); visited[u_new]=true;
control[u_new]=u;
op[u_new]=SWITCHON+i;
}
}
}
}
return -1;
}
void dfsprint(int u)
{
int u_new;
if (u==(1<<4)) return;
u_new=control[u];
dfsprint(u_new);
if (op[u]>=MOVETO) printf("- Move to room %d.\n", op[u]-MOVETO+1);
else if (op[u]>=SWITCHON) printf("- Switch on light in room %d.\n", op[u]-SWITCHON+1);
else if (op[u]>=SWITCHOFF) printf("- Switch off light in room %d.\n", op[u]-SWITCHOFF+1);
}
void print(int cs, int steps)
{
printf("Villa #%d\n", cs);
if (steps==-1)
printf("The problem cannot be solved.\n");
else
{
printf("The problem can be solved in %d steps:\n", steps);
dfsprint((1<<(r+4-1))+r-1);
}
printf("\n");
}
int main()
{
int steps;
for (int cs=1; ;cs++)
{
if (!init()) break;
steps=bfs();
print(cs, steps);
}
return 0;
}