——by A Code Rabbit
玩一个游戏。
输入房间的数量和每个房间的情况,包括每个房间通往哪几个房间。
输出是否能取得胜利。
注意:
Date Structure :: Graphs
注意这道题将会有回路。
通过回路,既可以使得你的能量无限大,但是你也可能在回路中出不来。
所以如果用搜索去做这道题,如何处理回路的情况是关键。
搜索的话有两种做法,DFS 和 BFS。
1. DFS
需要二重的 DFS,第一重就是常规地去走每一个能够走的房间。
而第二重,就是在第一重 DFS 时,碰到走过的房间,
如果此时能量大于上次来的时候的能量,就说明你可以利用这个回路来使自己的能量无穷大,此时,只要开启第二种 DFS ,看看你所在的房间,能否到达目的房间(路上无视计算能量的影响),即可。
如果此时能量小于或等于上次来的时候的能量,说明你没有必要走这个回路,退出搜索即可。
2. BFS
常规的 BFS ,不过在到底某个房间时,需要记录你到达这个房间的能量。
下次来到这个房间的时候,如果能量更低就不必将此时的状态入栈,如果能量更高就更新到达这个房间的能量值。
在搜索的时候,发现能量发生异常(能量值已经很大了,还没有退出队列),就说明这时候已经陷入环中无法自拔了,退出循环,判定游戏失败即可。
// UVaOJ 10557 // XYZZY // by A Code Rabbit #include <cstdio> #include <cstring> const int LIMITS = 120; struct Room { int energy; int doorways[LIMITS]; int num_doorways; int last_energy; }; Room room[LIMITS]; int n; bool is_visited[LIMITS]; bool CanArrive(int pos); bool Search(int pos, int energy); int main() { while (scanf("%d", &n), n != -1) { // Inputs and INIT status of rooms. for (int i = 1; i <= n; ++i) { scanf("%d%d", &room[i].energy, &room[i].num_doorways); for (int j = 0; j < room[i].num_doorways; ++j) { scanf("%d", &room[i].doorways[j]); } room[i].last_energy = -1; /* -1 means that the room is never visited. */ } // Outputs. printf("%s\n", Search(1, 100) ? "winnable" : "hopeless"); } return 0; } bool Search(int pos, int energy) { // Exit. if (energy <= 0) { return false; } // Judge whether this is target. if (pos == n) { return true; } // If enter this room secondly. if (room[pos].last_energy != -1) { if (energy > room[pos].last_energy) { /* ? */ memset(is_visited, false, sizeof(is_visited)); if (CanArrive(pos)) { return true; } } return false; }; // Continue. room[pos].last_energy = energy; for (int i = 0; i < room[pos].num_doorways; ++i) { int pos_room_new = room[pos].doorways[i]; if (Search(pos_room_new, energy + room[pos_room_new].energy)) { return true; } } return false; } bool CanArrive(int pos) { // Exit. if (is_visited[pos]) { return false; } // Judge whether this is target. if (pos == n) { return true; } // Continue. is_visited[pos] = true; for (int i = 0; i < room[pos].num_doorways; ++i) { if (CanArrive(room[pos].doorways[i])) { return true; } } return false; }
// UVaOJ 10557 // XYZZY // by A Code Rabbit #include <cstdio> #include <cstring> const int LIMITS_NUM_ROOM = 120; const int LIMITS_QUEUE = 1000000; const int LIMITS_ENERGY_NEED = 100000; struct Room { int energy; int doorways[LIMITS_NUM_ROOM]; int num_doorways; int last_energy; }; Room room[LIMITS_NUM_ROOM]; int n; struct Status { int pos; int energy; }; Status queue[LIMITS_QUEUE]; int head, tail; bool is_found; void BFS(); void INIT(); void Search(int pos, int energy); int main() { while (scanf("%d", &n), n != -1) { // Inputs and INIT status of rooms. for (int i = 1; i <= n; ++i) { scanf("%d%d", &room[i].energy, &room[i].num_doorways); for (int j = 0; j < room[i].num_doorways; ++j) { scanf("%d", &room[i].doorways[j]); } room[i].last_energy = 0; } // BFS. BFS(); // Outputs. printf("%s\n", is_found ? "winnable" : "hopeless"); } return 0; } void BFS() { INIT(); Search(1, 100); while (head < tail) { // Judge whether searching fall into loops. if (queue[head].energy > LIMITS_ENERGY_NEED) break; int pos_room = queue[head].pos; for (int i = 0; i < room[pos_room].num_doorways; ++i) { int pos_room_new = room[pos_room].doorways[i]; Search(pos_room_new, queue[head].energy + room[pos_room_new].energy); } ++head; } } void INIT() { head = 0; tail = 0; is_found = false; } void Search(int pos, int energy) { // Exit. if (is_found) { return; } if (energy <= 0) { return; } // Judge whether this is target. if (pos == n) { is_found = true; return; } // Update last energy of this room. if (energy > room[pos].last_energy) { room[pos].last_energy = energy; } else { return; } // Push. queue[tail].pos = pos; queue[tail].energy = energy; ++tail; }
下载PDF
参考资料:无