本题题目名字跟题目关系貌似不大,或者是因为我没看懂第一段。本题是说有最多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; }