题目大意:就是一款游戏,冒险本来的能量是100,每进一间屋子就可以把屋子里的能量占为己有,但是屋子能量有正有负,然后给起点终点,看能否成功的到达终点。并且一间屋子可以重复进去多次。
解题思路:刚开始想用dfs, 但是题目里面会有环,会出现死循环,一直没想到思路。后来看了别人的代码。才发现可以巧妙的用dfs和bfs。
bfs()是用来只寻找是否有到达终点的通道。
dfs()是用来模拟冒险的,一间房间可能会被进去多次,这时就需要判断第二次是,是否比前一次要多,如果是的话,就说明可以通过这条路来累计能量,这样就可以过关。如果比原来的要少,就要判断别的路径是否可能。如果中途能量不足就直接out了。
#include<stdio.h>
#include<string.h>
const int N = 105;
int n, room[N][N], v[N], visit[N];
int energy[N], flag;
int q[N * N];
int bfs(int x) {
memset(visit, 0, sizeof(visit));
memset(q, 0, sizeof(q));
int front = 0;
int rear = 0;
q[rear++] = x;
visit[x] = 1;
while(front < rear) {
x = q[front++];
for(int i = 1; i <= n; i++) {
if(room[x][i] && !visit[i]) {
visit[i] = 1;
if(i == n)
return 1;
q[rear++] = i;
}
}
}
return 0;
}
void dfs(int x, int e) {
if(x == n) {
flag = 1;
return;
}
for(int i = 1; i <= n; i++) {
if(room[x][i] && !flag && e + v[i] > 0) {
if(!energy[i] ) {
energy[i] = e + v[i];
dfs(i, e + v[i]);
}
else if(energy[i] < e + v[i] && bfs(i))
flag = 1;
}
}
}
int main() {
while(scanf("%d", &n) , n != -1) {
int i, j, m, num;
memset(room, 0, sizeof(room));
memset(v, 0, sizeof(v));
memset(energy, 0, sizeof(energy));
for(i = 1; i <= n; i++) {
scanf("%d%d", &v[i], &num);
for(j = 1; j <= num; j++) {
scanf("%d", &m);
room[i][m] = 1;
}
}
flag = 0;
energy[1] = 100;
dfs(1, 100);
if(flag)
printf("winnable\n");
else
printf("hopeless\n");
}
return 0;
}
这题一直卡着,主要在审题不清,起点终点明明交代清楚了,竟然没看到,按照自己的想法来找起点,结果出错了。