題目:有1~r個房間,房間之間有聯通順序,每個房間有一些控其他房間的燈的開關,
初始1號房間燈亮著,其他燈熄滅,每次可以選著撥動當前房間的開關,
或者移動到相鄰的亮著燈的房間,問最少執行多少操作,能走到最後一個房間,
並且除了最後的房間外,其他房間都是暗的。
分析:搜索,狀態壓縮。利用4096*room_id + Σ(1<<switch_i)作为状态,bfs即可。
狀態由兩部分組成,4090*房間ID+對應每個燈的開關狀態。
說明:╮(╯▽╰)╭。
#include <cstring>
#include <cstdio>
int link[11][11], switchs[11][11];
int front[50000];
int output(int start, int over, int deep)
{
if (start != over) {
output(start, front[over], deep+1);
int room1 = front[over]/4096;
int room2 = over/4096;
if (room1 == room2) {
int state = 0;
while ((1<<state) < (front[over]^over)) {
state ++;
}
if ((1<<state)&front[over]) {
printf("- Switch off light in room %d.\n",state);
}else {
printf("- Switch on light in room %d.\n",state);
}
}else {
printf("- Move to room %d.\n",room2);
}
}else {
printf("The problem can be solved in %d steps:\n",deep);
}
}
int visit[50000], queue[50000];
int bfs(int n, int start, int over)
{
if (start == over) {
printf("The problem can be solved in 0 steps:\n");
return 1;
}
int head = 0, tail = 0;
queue[tail ++] = start;
visit[start] = 1;
while (head < tail) {
int New, now = queue[head ++];
int room = now/4096;
//printf("now : [%d]\n",now);
for (int i = 1; i <= n; ++ i) {
if (link[room][i]) {
New = now%4096+i*4096;
if (((1<<i)&New) && !visit[New]) {
//printf("new : [(%d)%d]\n",(1<<i)&New,New);
visit[New] = 1;
front[New] = now;
queue[tail ++] = New;
if (New == over) {
output(start, over, 0);
return 1;
}
}
}
if (switchs[room][i]) {
New = now^(1<<i);
if (((1<<room)&New) && !visit[New]) {
//printf("new : [%d]\n",New);
visit[New] = 1;
front[New] = now;
queue[tail ++] = New;
if (New == over) {
output(start, over, 0);
return 1;
}
}
}
}
}
return 0;
}
int main()
{
int r, d, s, room1, room2, light, cases = 1;
while (~scanf("%d%d%d",&r,&d,&s) && r+d+s) {
memset(link, 0, sizeof(link));
memset(switchs, 0, sizeof(switchs));
memset(visit, 0, sizeof(visit));
for (int i = 1; i <= d; ++ i) {
scanf("%d%d",&room1,&room2);
link[room1][room2] = 1;
link[room2][room1] = 1;
}
for (int i = 1; i <= s; ++ i) {
scanf("%d%d",&room1,&light);
switchs[room1][light] = 1;
}
printf("Villa #%d\n",cases ++);
if (!bfs(r, 4098, r*4096+(1<<r))) {
puts("The problem cannot be solved.");
}
puts("");
}
return 0;
}
測試數據:
5 4 5
1 2
1 3
1 4
1 5
1 2
2 3
3 4
4 5
5 1
3 3 4
1 2
1 3
3 2
1 2
1 3
2 1
3 2
2 1 2
2 1
1 1
1 2
4 4 7
1 4
1 2
2 3
3 4
1 2
1 3
2 4
2 1
3 2
2 3
4 3
4 4 6
1 4
1 2
2 3
3 4
1 2
2 3
3 4
4 2
3 1
4 3
1 0 1
1 1
1 0 0
2 0 0
5 4 5
1 2
1 3
1 4
1 5
1 2
2 3
3 4
4 5
5 1
5 4 5
1 2
1 3
2 4
1 5
1 2
2 3
3 4
4 5
5 1
10 9 13
1 2
2 3
3 4
1 5
4 6
1 7
4 8
1 9
4 10
1 2
2 3
3 4
4 5
5 6
6 7
7 8
8 9
9 10
2 1
3 2
4 3
10 4
0 0 0