Problem D: XYZZY
ADVENT: /ad�vent/, n.
The prototypical computer adventure game, first designed by Will Crowther on the PDP-10 in the mid-1970s as an attempt at computer-refereed fantasy
gaming, and expanded into a puzzle-oriented game by Don Woods at Stanford in 1976. (Woods had been one of the authors of INTERCAL.) Now better known as Adventure or Colossal Cave Adventure, but the TOPS-10 operating system permitted only six-letter filenames in uppercase. See also vadding, Zork, and Infocom.
(neglect above !!)
題目類似於一個闖關的游戲,開始滿血值為100,闖關的每個房子都有其對應的“能量”,能量有正有負,進去之后就獲得能量(你的血量加上房子的能量,結果可能為負數)如果到出口之前你的血量為零或負數,那么這時你就失敗輸出"hopeless",注意房子可以重復進去,所以可能會有能量一直增長的循環,這里要進行判斷。房子之間相不相連在輸入時已經有給說明(鄰接表的形式說明)
Each game consists of a set of up to 100 rooms. One of the rooms is the start and one of the rooms is thefinish. Each room has an energy value between -100 and +100. One-way doorways interconnect pairs of rooms.
The player begins in the start room with 100 energy points. She may pass through any doorway that connects the room she is in to another room, thus entering the other room. The energy value of this room is added to the player's energy. This process continues until she wins by entering the finish room or dies by running out of energy (or quits in frustration). During her adventure the player may enter the same room several times, receiving its energy each time.
The input consists of several test cases. Each test case begins with n, the number of rooms. The rooms are numbered from 1 (the start room) to n (the finish room). Input for the n rooms follows. The input for each room consists of one or more lines containing:
- the energy value for room i
- the number of doorways leaving room i
- a list of the rooms that are reachable by the doorways leaving room i
The start and finish rooms will always have enery level 0. A line containing -1 follows the last test case.
In one line for each case, output "winnable" if it is possible for the player to win, otherwise output "hopeless".
Sample Input
5 0 1 2 -60 1 3 -60 1 4 20 1 5 0 0 5 0 1 2 20 1 3 -60 1 4 -60 1 5 0 0 5 0 1 2 21 1 3 -60 1 4 -60 1 5 0 0 5 0 1 2 20 2 1 3 -60 1 4 -60 1 5 0 0 -1
Output for Sample Input
hopeless hopeless winnable winnable
G. V. Cormack
#include<stdio.h> #include<string.h> #include<malloc.h> #define MAXN 110 typedef struct{ int value, visit; }maze; // value的作用:1是可以存儲能量,2是存儲跟當前房子連接的房子的數量;visit的作用是在遍歷的時候查看是否已被遍歷,
// 並且存儲將要遍歷時當前闖關人的血的能量 maze game[MAXN][MAXN]; int flag = 0; /* void PrintMaze(int n) { int i, j; for(i=1; i<=n; ++i) { printf("[%d]: energy = %d, listnumber = %d\n", i, game[0][i].value, game[i][0].value); for(j=1; j<=game[i][0].value; ++j) { printf("%d[%d] ", game[i][j].value, game[i][j].visit); } printf("\n"); } return; } */ int TraverseOut(int u, int n) {//TraverseOut函數的作用是通過廣度查找,查看u節點跟出口是否連接,如果連接返回1, 否則返回0 int visit[MAXN], queue[MAXN]; int front, rear, i, t, j; memset(visit, 0, sizeof(visit)); front = rear = 0; visit[u] = 1; queue[rear++] = u; while(front < rear) { t = queue[front++]; for(i=1; i<=game[t][0].value; ++i) if(!visit[game[t][i].value]) { if(n == game[t][i].value) return 1; queue[rear++] = game[t][i].value; visit[game[t][i].value] = 1; } } return 0; } void Traverse(int current, int n, int energy) {// Traverse函數的作用是通過深度查找模擬題目情景~~ int i, j, cnt, m; energy = energy + game[0][current].value; if(energy > 0 && current == n) {//如果能量大於零而且到達了重點,則flag = 1並返回 flag = 1; return; } else if(energy <= 0) return; //夭折了也要返回 for(i=1; i<=game[current][0].value; ++i) { // m = game[0][game[current][i].value].value; if(game[current][i].visit != 0) {//不等於零說明之前已經有走過這間房子,而且里面保存的是將要進去這間房子時的血量 if(game[current][i].visit < energy && TraverseOut(game[current][i].value, n)) {//滿足:回來的時候血量比之前增加了,而且這間房到終點有通路 flag = 1; return; } else continue; } else game[current][i].visit = energy; Traverse(game[current][i].value, n, energy); if(flag) return; /* game[current][i].visit = 0; */ //因為這里讓超時不斷啊 } return; } int main() { int n, m, i, j, cnt, sum; while(scanf("%d", &n) != EOF && n != -1) { for(i=1; i<=n; ++i) {//game矩陣中第一行存儲對應號數房子的能量值 scanf("%d", &game[0][i].value); scanf("%d", &game[i][0].value); //第二行開始每一行的第一個位置存儲跟它連接的房子的數量,后面緊接着存儲房子的“地址” game[i][0].visit = 0; for(j=1; j<=game[i][0].value; ++j) { scanf("%d", &game[i][j].value); game[i][j].visit = 0; } } /* PrintMaze(n); */ sum = 100; flag = 0, cnt = 1; Traverse(cnt, n, sum); if(flag) printf("winnable\n"); else printf("hopeless\n"); } return 0; }
解題思路:
DFS+BFS