题目意思:给定n个编号为1-n的房间,每个房间有对应的能量值(-100 - 100),还有给定每一个房间的门的个数,以及通过这些门可以到哪些房间,有一个人从起始点(默认为0房间)开始走,问能否走到终点n房间,如果中间的能量为0或小于0则直接算不能到达。
解题思路:对于过去的搜索题,我么通常用一个vis[]数组标记是否走过,对于这题我么另vis[]数组存储的是从开始到这个点的能量值,还有我们用一个局部遍历energy表示从开始到当前点的能量的变化值(增加就是这个过程能量增大,反之),其它见一下代码,详解。
代码:
//直接dfs,我们知道对于有往回走的点 ,如果往回走的过程能量在增加,那么可知我们无限循环时可得到无穷的能量,所以这时候我们在用一个dfs去判断是否这一点可以达终点如果可以直接退出,不行返回进行下一步。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <queue>
#include <stack>
using namespace std;
const int MAXN = 110;
int vis[MAXN], mark[MAXN];//mark数组用来标记走过的路径(在判断是否可以到终点的dfs中用到)
int room[MAXN][MAXN]; //第一数是能量,第二个数是门的个数,第三个开始是能到的房间的编号
int n, flag;
//搜索是否能到最后点
void Dfs(int k) {
if (mark[k])//如果走过该房间则退出
return;
if (k == n) {//到最后时候也退出
flag = 1;//更新flag的值
return;
}
if (mark[k] == 0) {//如果没走过
mark[k] = 1;//标记上一点走过了
for (int j = 0; j < room[k][1]; j++) {
if (mark[room[k][j + 2]] == 0) {
Dfs(room[k][j + 2]);//对每一个可能的情况Dfs
}
}
}
}
//深搜求解能量
//这里我们就用一个局部变量energy表示从起始点到该位置的能量的变化值(有正有负),这样就可以对于每一个函数都有一个energy,所以这里要用局部变量,全局会出错
void dfs(int i , int energy) {
vis[i] = 100 + energy;//求出当前点的能量总和
if (vis[i] <= 0){//如果小于0,那么就直接退出
return;
}
if (i == n) {//如果到终点就更新flag,退出
flag = 1;
return;
}
if (vis[i] > 0) {//大于0,继续向一步走
for (int j = 0; j < room[i][1]; j++) {//遍历每一个可以到的房间
if (vis[room[i][j + 2]] == -1) {//如果没被走过,直接往下走
int k = room[i][j+2];
dfs(room[i][j + 2] , energy + room[k][0]);//这里energy是加上room[k][0],说明到下一点的能量总的变化
}
else {//如果走过,那么判断是否是能量增加
int k = room[i][j+2];
if (room[k][0] + energy + 100 > vis[k]) {//判断重新走到这个点的值room[k][0] + energy + 100是否大于上一次的值vis[k]。
memset(mark, 0, sizeof (mark));//每次都要初始化为0
Dfs(i);//判断i这个点能否到终点(传K也一样)
if(flag)//如果可以到终点直接退出
return;
}
}
}
}
}
//处理问题函数
void solve() {
memset(vis, -1, sizeof (vis));
flag = 0;//默认是为0
vis[0] = 100;//起始点为100
dfs(1 , 0);
if (flag)
printf("winnable\n");
else
printf("hopeless\n");
}
//主函数
int main() {
while (scanf("%d", &n) && n != -1) {//输入注意一下
for (int i = 1; i <= n; i++) {
scanf("%d %d", &room[i][0], &room[i][1]);
for (int k = 0; k < room[i][1]; k++)
scanf("%d", &room[i][k + 2]);
}
solve();
}
return 0;
}