[ZOJ1301][POJ1137] The New Villa
来源:互联网 发布:网易贵金属行情软件 编辑:程序博客网 时间:2024/06/06 11:01
ZOJ: http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=1301
POJ: http://poj.org/problem?id=1137
每个房间的开关经常是控制别的房间的灯的。
Mr.Black站在走廊,灯全是熄灭的。Mr.Black怕黑,所以他不敢进入黑的屋子,也不敢关掉他所在屋子的灯。
走廊是亮的,所有屋子是黑的。不准走进黑屋子,且最后到达卧室,卧室以外的灯全灭。找到步骤最小的方式,“房间之间的移动”、“开灯”、“关灯”都算一个步骤。
解题思路:
由求最短步骤和r很小,且灯的状态可以用01表示,想到可以用广搜。
状态最多1024*10种,每种最多有10种移动方式+10种开灯方式+10种关灯方式共30种操作,时间上是允许广搜的。
注意点:
1、写输出部分的时候犹豫了一下,把步骤等于0和1的地方写了step的单数形式,步骤大于1的时候使用step复数形式,结果居然WA掉了。
2、注意操作步骤和短线"-"之间有空格,之后才注意到的,果然还是应该把sample output复制到记事本里看……
源代码:
#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 0int r;int control[maxs]; //状态转移i由control[i]得到 int op[maxs]; //状态i通过op[i]由上一步得到 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)); //g[i][j]==true 表示房间ij之间互通 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)); //-1: 无控制, i控制light[i] 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() //return -1 or number of steps{ 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;} //状态低4位留给位置 for (int i=0; i<r; i++) //move操作 { if (g[pos][i]) //可以从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;}
- [ZOJ1301][POJ1137] The New Villa
- zoj1301 The New Villa
- 321 - The New Villa
- POJ 1137 The New Villa
- uva 321 - The New Villa
- UVa 321 - The New Villa
- UVA 321 - The New Villa
- uva 321 - The New Villa
- uvaoj 321 - The New Villa
- POJ 1137----The New Villa
- uva 321 The New Villa
- UVa 321 - The New Villa
- UVA - 321 The New Villa
- uva 321 - The New Villa bfs+递归
- uva321 - The New Villa(新别墅)
- uva:321 - The New Villa(bfs + 哈希判重)
- The New Villa -uva 隐式图搜索
- UVa 321 & ZOJ 1301 - The New Villa
- VB 对话框窗口的使用
- 关于 !define /date
- Problem:"Invalid command: ${GetTime}"
- Trac - 为Tickets增加自定义字段
- SQLSERVER2008安装问题(挂起重新启动会导致安装程序失败 )
- [ZOJ1301][POJ1137] The New Villa
- ASP.NET 发布水晶报表(vs2008 en)
- linux setlocale用法
- javascript是大小写敏感的
- 使用独立的node windows二进制文件
- .NET组件程序设计 第8章 多线程和并发管理
- C基本知识
- Linux环境下配置动态链接库
- Javascript在页面加载时的执行顺序