本题题目名字跟题目关系貌似不大,或者是因为我没看懂第一段。本题是说有最多100个room,每个room有一个值,从1号room、100体力值开始,通过某种路径走到n号room,每到一个房间就加上或减去相应的体力值。要求过程中体力值不能小于0 。等于0的临界情况是否算die不清楚。。。两种理解都可以过。
因为存在可以通过转圈来积攒体力,即存在环,所以单独的floyed和迪杰斯特拉无法求解,需用Bellman-Ford来对付,但是在松弛过程中又需要保证松弛的点最终是可以到达终点的,即“如果存在环,那么终点应该在环中”。所以先用floyed来判断各个点是否能通向终点,松弛过程中只对能到达终点的点进行松弛,而不能到达终点的点,可行方案中一定不会走到,所以在松弛过程中不予理会。
此题也可以用单独的SPFA来做。
//9040551 NKHelloWorld 1932 Accepted 188K 235MS C++ 1819B 2011-07-30 21:43:36
//9040553 NKHelloWorld 1932 Accepted 412K 219MS G++ 1819B 2011-07-30 21:43:57
#include <cstdio>
#include <cstring>
int n,value[110],dis[110];
bool map[110][110],connected[110][110];
int main()
{
int i,j,k,m;
while(scanf("%d",&n)!=EOF && n!=-1)
{
memset(map,false,sizeof(map));
memset(connected,false,sizeof(connected));
memset(dis,-1,sizeof(dis));
for(i=1;i<=n;i++)
{
scanf("%d%d",&value[i],&m);
for(j=1;j<=m;j++)
{
scanf("%d",&k);
map[i][k] = true;
connected[i][k] = true;
}
}
for(k=1;k<=n;k++)
{
for(i=1;i<=n;i++)
{
for(j=1;j<=n;j++)
{
if(map[i][k] && map[k][j])
map[i][j] = true;
}
}
}
map[n][n] = true;//保证终点自己成环,下面Bellman-Ford会涉及到
if(!map[1][n])
{
printf("hopeless\n");
continue;
}
bool flag = true;
dis[1] = 100;
for(k=1;k<=n;k++)
{
flag = true;
for(i=1;i<=n;i++)
{
for(j=1;j<=n;j++)
{
if(connected[i][j])
{
if(dis[j] < dis[i]+value[j] && map[j][n] && dis[i]>0)//保证一旦形成环时终点是包含在环里的
{
dis[j] = dis[i]+value[j];
flag = false;
}
}
}
}
if(flag)
break;
}
if(k>n || dis[n]>=0)
{
printf("winnable\n");
}
else
printf("hopeless\n");
}
return 0;
}