对每一个状态进行遍历,用door来表示当前所在的房间,state[10]表示各个房间的开关情况,每次进行一步移动
总状态为10*2^10.用hash来判重。用一个状态数组flag来记录每一次是进行的什么操作。最终状态为所在房间为r,只有r房的灯开着的。
每次只考虑一步就行了,从小到大的开。一开始考虑复杂了,考虑到可能开一盏灯,然后还要从控制中选一盏,或者两盏灯等等。其实每次只要一步,这些开多盏灯的状态都可以从一次开一盏,一次开一盏的状态衍生出来。最近做了很多的搜索。貌似解答树类型的都用深搜,隐式图类型的都用广搜。注意坑爹的是r=1的时候要输出0步。被这坑了N久的时间.....
AC代码:
#include<iostream>
#include<cstring>
using namespace std;
const int MaxSize=20000;
const int HashTable=10007;
struct Node{
int door,fa,dist;
int to_do;
int state[12];
};
int head[HashTable],Next[MaxSize];
Node st[MaxSize];
int flag[MaxSize];
int Maps[20][20];
int final_state[12];
int Links[20][20],have_find,r,d,s;
void print_path(int fa){
if(st[fa].fa!=-1)
print_path(st[fa].fa);
if(flag[fa]==1){
cout << "- Move to room " << st[fa].to_do << ".\n";
}
if(flag[fa]==2){
cout << "- Switch off light in room " << st[fa].to_do << ".\n";
}
if(flag[fa]==3){
cout << "- Switch on light in room " << st[fa].to_do << ".\n";
}
}
int Hash(int a[]){
int i,v;
for(i=1,v=0;i<=10;i++){
v=(v<<1)+a[i];
}
return v%HashTable;
}
bool try_to_insert(int s){
int h=Hash(st[s].state);
int u=head[h];
while(u){
if(memcmp(st[u].state,st[s].state,sizeof(st[u].state))==0&&st[u].door==st[s].door)
return false;
u=Next[u];
}
Next[s]=head[h];
head[h]=s;
return true;
}
int bfs(void){
int front=1,rear=2,i;
st[1].door=1;
st[1].fa=-1;
st[1].dist=0;
st[1].state[1]=1;
final_state[r]=1;
try_to_insert(1);
while(front<rear){
Node &now=st[front];
if(memcmp(now.state,final_state,sizeof(final_state))==0&&now.door==r){
have_find=1;
return front;
}
for(i=1;i<=r;i++){
if(Maps[now.door][i]&&now.state[i]){
memcpy(st[rear].state,now.state,sizeof(now.state));
st[rear].door=i;
st[rear].fa=front;
st[rear].dist=now.dist+1;
st[rear].to_do=i;
flag[rear]=1;
if(try_to_insert(rear))
rear++;
}
}
for(i=1;i<=r;i++){
if(Links[now.door][i]&&i!=now.door){
memcpy(st[rear].state,now.state,sizeof(now.state));
st[rear].door=now.door;
st[rear].dist=now.dist+1;
st[rear].fa=front;
if(now.state[i]==1){
st[rear].state[i]=0;
st[rear].to_do=i;
flag[rear]=2;
if(try_to_insert(rear))
rear++;
}
else{
st[rear].state[i]=1;
st[rear].to_do=i;
flag[rear]=3;
if(try_to_insert(rear))
rear++;
}
}
}
front++;
}
have_find=0;
return 0;
}
int main()
{
int i,do1,do2,case_num=1,state_num;
while(cin>>r>>d>>s,(r||d||s)){
memset(final_state,0,sizeof(final_state));
memset(Maps,0,sizeof(Maps));
memset(Links,0,sizeof(Links));
memset(head,0,sizeof(head));
have_find=0;
for(i=1;i<=d;i++){
cin >> do1 >> do2;
Maps[do1][do2]=Maps[do2][do1]=1;
}
for(i=1;i<=s;i++){
cin >>do1 >> do2;
Links[do1][do2]=1;
}
state_num=bfs();
cout << "Villa #" << case_num << endl;
if(st[state_num].dist!=0)
cout << "The problem can be solved in "<<st[state_num].dist << " steps:" << endl;
case_num++;
if(r==1)
cout << "The problem can be solved in 0 steps:\n";
if(have_find){
print_path(state_num);
cout << endl;
}
else{
cout << "The problem cannot be solved." << endl;
cout << endl;
}
}
return 0;
}