题意:从客厅走到卧室,到达卧室后,除卧室之外的灯全关。还有一点就是走到哪个房间,那个房间的灯必须亮着。
思路:1.BFS输出距离最短的,每次只记录一个状态,类似于穷举。
2.开灯算一步。关灯算一步。从一个房间走向另一个房间算一步。
3.从客厅开始。
用当前位置和灯的状态HASH判重即可。
注意只有一个房间的情况,真的是太坑了,WA了好几天,最后还是参考别人代码才发现的,而且单词还打错了,solved写成了sovled。
#include<stdio.h>
#include<string.h>
#define MAXSIZE 100003
#define OFF 3
#define ON 1
#define MOVE 2
int test=0;
int path[11][11];//room paths
int control[11][11];//switch control
int r,d,s;
typedef struct mo{
int CRoom;//current room where your are
int light[11];//1 stands for open, 0 stands for close
int step;
int father;
int DRoom;
int state;//move or push the switch
}M;
M move[MAXSIZE];
int head[MAXSIZE],next[MAXSIZE];
int goal[11];
void Initial()
{
int i;
for(i=0;i<1;i++)
{
move[i].CRoom=1;
memset(move[i].light,0,sizeof(move[i].light));
move[i].light[1]=1;
move[i].step=0;
move[i].state=0;
move[i].father=-1;
move[i].DRoom=1;
}
memset(goal,0,sizeof(goal));
memset(head,0,sizeof(head));
memset(next,0,sizeof(next));
goal[r]=1;
}
void OperateLight(int n,int dest,int currentLight)
{
if(currentLight==0)
{
move[n].light[dest]=1;
move[n].DRoom=dest;
move[n].state=ON;
}
else
{
move[n].light[dest]=0;
move[n].DRoom=dest;
move[n].state=OFF;
}
move[n].step++;
}
void OutPut(int n)
{
if(n==-1)return;
OutPut(move[n].father);
if(move[n].state==MOVE)
{
printf("- Move to room %d.\n",move[n].CRoom);
}
if(move[n].state==ON)
{
printf("- Switch on light in room %d.\n",move[n].DRoom);
}
if(move[n].state==OFF)
{
printf("- Switch off light in room %d.\n",move[n].DRoom);
}
}
int AccessGoal(int n)
{
if(!memcmp(goal,move[n].light,sizeof(goal))&&move[n].CRoom==r)
{
printf("Villa #%d\n",test);
printf("The problem can be solved in %d steps:\n",move[n].step);
OutPut(n);
return 1;
}
return 0;
}
int hash(int n)
{
int i,v=0;
for(i=1;i<=r;i++)
{
v=v*2+move[n].light[i];
}
return v%MAXSIZE;
}
int isExist(int n)
{
int h,u;
h=hash(n);
u=head[h];
while(u)
{
if(!memcmp(move[u].light,move[n].light,sizeof(move[u].light))&&move[u].CRoom==move[n].CRoom)return 1;
u=next[u];
}
next[n]=head[h];
head[h]=n;
return 0;
}
void BFS()
{
int front=0,rear=1;
int i,j,k;
M current;
while(front<rear)
{
memcpy(¤t,&move[front],sizeof(M));
//check
if(AccessGoal(front))return;
//enter room
for(i=1;i<=r;i++)
{
if(path[current.CRoom][i]&¤t.light[i])//light is on,move in
{
memcpy(&move[rear],¤t,sizeof(M));
move[rear].CRoom=move[rear].DRoom=i;
move[rear].state=MOVE;
move[rear].step++;
if(!isExist(rear))
{
move[rear].father=front;
rear++;
}
}
}
//push switch
for(i=1;i<=r;i++)
{
if(control[current.CRoom][i]&&i!=current.CRoom)
{
memcpy(&move[rear],¤t,sizeof(M));
OperateLight(rear,i,current.light[i]);
if(!isExist(rear))
{
move[rear].father=front;
rear++;
}
}
}
front++;
}
printf("Villa #%d\n",test);
printf("The problem cannot be solved.\n");
}
int main()
{
int i,j,k;
int x,y;
while(scanf("%d%d%d",&r,&d,&s)!=EOF&&(r||d||s))
{
test++;
Initial();
memset(path,0,sizeof(path));
memset(control,0,sizeof(control));
for(i=0;i<d;i++)
{
scanf("%d%d",&x,&y);
path[x][y]=1;
path[y][x]=1;
}
for(i=0;i<s;i++)
{
scanf("%d%d",&x,&y);
control[x][y]=1;
}
if(r==1)
{
printf("Villa #%d\n",test);
printf("The problem can be solved in 0 steps:\n\n");
continue;
}
BFS();
printf("\n");
}
return 0;
}