本题题目名字跟题目关系貌似不大,或者是因为我没看懂第一段。本题是说有最多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;
}
posted on 2011-07-30 21:56  NKHe!!oWor!d  阅读(324)  评论(0编辑  收藏  举报