隐式图搜索,需将所有房间亮着的灯和当前位置的整体的状态抽象为图中的一个节点,进行搜索
#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
#define MAX_SIZE 10000
#define MOV 1
#define ON 2
#define OFF 3
typedef struct _node
{
int room;
int parent;
int dist;
int oper;
int to;
int state[12];
}Node;
int goal[12];
int r,d,s;
char G[20][20];
char control[20][20];
Node q[MAX_SIZE];
int head[MAX_SIZE],next[MAX_SIZE];
void input()
{
int x,i,j;
memset(G, 0, sizeof(G));
memset(control,0,sizeof(control));
memset(q,0,sizeof(q));
memset(goal,0,sizeof(goal));
memset(head,0,sizeof(head));
memset(next,0,sizeof(next));
for(x=0; x<d; x++)
{
scanf("%d %d",&i, &j);
G[i][j] = 1;
G[j][i] = 1;
}
for(x=0; x<s; x++)
{
scanf("%d %d",&i, &j);
control[i][j] = 1;
}
goal[r] = 1;
}
#define HASH 10240
int hash(int arr[])
{
int x=0;
for(int i=1; i<=10; i++)
x = (x<<1) | arr[i];
return x%HASH;
}
int try_insert(int rear)
{
int h = hash(q[rear].state);
int u = head[h];
while(u)
{
if(memcmp(q[rear].state,q[u].state,sizeof(goal))==0 && q[rear].room==q[u].room)
return 0;
u = next[u];
}
next[rear] = head[h];
head[h] = rear;
return 1;
}
int solve(int n)//n房间号
{
int front=1,rear=2,i,j;
q[front].parent = -1;q[front].room = 1;q[front].state[1] = 1;
try_insert(1);
while(front<rear)
{
Node& cur = q[front];
if(memcmp(cur.state,goal,sizeof(goal))==0 && cur.room==r)
return front;
//是否有可行通路
for(i=1; i<=r; i++)
{
if(G[cur.room][i] && cur.state[i])
{
memcpy(&q[rear], &cur, sizeof(Node));
q[rear].dist += 1;
q[rear].oper = MOV;
q[rear].parent= front;
q[rear].room = i;
q[rear].to = i;
if(try_insert(rear))
rear++;
}
}
//是否有开关灯操作
for(i=1; i<=r; i++)
{
if(control[cur.room][i] && (cur.room!=i) )
{
memcpy(&q[rear], &cur, sizeof(Node));
if(cur.state[i])
q[rear].oper = OFF;
else
q[rear].oper = ON;
q[rear].dist += 1;
q[rear].parent = front;
q[rear].state[i] = !q[rear].state[i];
q[rear].to = i;
if(try_insert(rear))
rear++;
}
}
front++;
}
return 0;
}
void output(int cur)
{
int i;
if(cur==-1)
return;
output(q[cur].parent);
switch(q[cur].oper)
{
case MOV:
printf("- Move to room %d.\n",q[cur].to);
break;
case ON:
printf("- Switch on light in room %d.\n",q[cur].to);
break;
case OFF:
printf("- Switch off light in room %d.\n",q[cur].to);
break;
}
}
int main()
{
int res=-1,cs=0;
while(scanf("%d %d %d",&r,&d,&s)==3)
{
if(r==0) break;
if(res==0) printf("\n\n");
input();
res = solve(1);
printf("Villa #%d\n",++cs);
if(res==0) printf("The problem cannot be solved.");
else
{
printf("The problem can be solved in %d steps:\n",q[res].dist);
output(res);printf("\n");
}
}
return 0;
}