最短路(Floyd)-hdu1317

题目链接:https://vjudge.net/problem/HDU-1317

题目描述:

  题意:玩家起始有100个能量点,刚开始在起始房间中,每个房间外有一条单向的路径通往其他房间(一个房间可能通往多个房间),具体通往哪些房间可以查看房间门口的房间列表。每次玩家进入一个房间,他的能量值会更新成 当前自身能量值+房间能量值(重点是房间的能量值可能为负值)。玩家想要终止游戏的话,要么是能够进入到终点房间,要么是因能量耗尽而累死。需要我们判断玩家能否进入到终点房间。

  Floyd算法(Floyd-Warshall algorithm)又称为弗洛伊德算法、插点法,是解决给定的加权图中顶点间的最短路径的一种算法,可以正确处理有向图或负权的最短路径问题,同时也被用于计算有向图的传递闭包。(百度百科)

  因为此题中存在负权值,因此用Floyd最短路来解决。

  思路:首先我们需要检查是否存在这样的路从1到达N,如果不存在,直接输出hopeless。我们可以利用floyd算法去检查。Floyd-Warshall算法是一种在具有正或负边缘权重(但没有负周期)的加权图中找到最短路径的算法。因为题中可能会出现负周期——行成环路,可以无限增加能量值。但是可以用于检查1到N是否连通。然后我们再使用Bellman算法,如果松弛N-1次后,任然存在更新。说明图中存在负周期,说明能量可以无限叠加,检查环路的点是否与N连通就行了。如果不存在负周期,则检查到达N的能量是否大于0。转载自博文:https://blog.csdn.net/rainbow_storm/article/details/81263440

代码实现:

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
int N,M;
const int MAXN =105;
const int INF = 0x3f3f3f3f;
/*    d数组表示到达i房间的最大的能量值;
    p数组表示每个房间的能量值;
    G数组存图。G[i][j]=1,表示i到j有1条通路。
    E数组存边。
*/
struct edge{
    int from,to;
}E[MAXN*MAXN];
int d[MAXN],P[MAXN];
int G[MAXN][MAXN];
bool floyd()//判断是否房间之间是可达的,如不可达,则输出hopeless
{
    for(int k=1;k<=N;k++)
        for(int i=1;i<=N;i++)
            for(int j=1;j<=N;j++)
                if(G[i][k]&&G[k][j])
                    G[i][j]=1;
    return G[1][N];
}

bool bellman(){
    fill(d,d+MAXN,-INF);
    d[1]=100;//初始值为100
    for(int i=1;i<N;i++)
    {
        bool flag=false;
        for(int j=0;j<M;j++){
            if(d[E[j].to] < d[E[j].from]+P[E[j].to] && d[E[j].from]+P[E[j].to]>0){
                flag=true;
                d[E[j].to]=d[E[j].from]+P[E[j].to];
            }
        }
        if(!flag) break;
    }
    for(int j=0;j<M;j++){
        if(d[E[j].to] < d[E[j].from]+P[E[j].to] && d[E[j].from]+P[E[j].to]>0){
            d[E[j].to]=d[E[j].from]+P[E[j].to];
            if(G[E[j].to][N]){
                return true;
            }
        }
    }
    return d[N]>0;
}

int main(){
    while(~scanf("%d",&N)&&(N!=-1)){
        memset(G,0,sizeof(G));
        memset(E,0,sizeof(E));
        memset(P,0,sizeof(P));
        M=0;
        int con;//记录连接多少扇门
        for(int i=1;i<=N;i++){
            scanf("%d%d",&P[i],&con);
            for(int j=1;j<=con;j++){
                int tmp;scanf("%d",&tmp);
                E[M++]=(edge){i,tmp};
                G[i][tmp]=1;//说明从门i到门tmp是可达的
            }
        }
        if(!floyd()){
            printf("hopeless\n");
            continue;
        }
        if(bellman()){
            printf("winnable\n");
        }else{
            printf("hopeless\n");
        }
    }
    return 0;
}

原文地址:https://www.cnblogs.com/LJHAHA/p/10014757.html

时间: 2024-10-27 09:06:01

最短路(Floyd)-hdu1317的相关文章

SDUT 2930-人活着系列之开会(最短路Floyd)

人活着系列之开会 Time Limit: 1000ms   Memory limit: 65536K  有疑问?点这里^_^ 题目描述 人活着如果是为了事业,从打工的到老板的,个个都在拼搏,奋斗了多年终于有了非凡成就,有了一笔丰富的钱财.反过来说,人若赚取了全世界又有什么益处呢?生不带来,死了你还能带去吗?金钱能买保险,但不能买生命,金钱能买药品,但不能买健康,人生在世,还是虚空呀! 在苍茫的大海上,有很多的小岛,每个人都在自己的小岛上.又到了开会的时候了,鹏哥通过飞信告知了每个人,然后大家就开

【bzoj2324】[ZJOI2011]营救皮卡丘 最短路-Floyd+有上下界费用流

原文地址:http://www.cnblogs.com/GXZlegend/p/6832504.html 题目描述 皮卡丘被火箭队用邪恶的计谋抢走了!这三个坏家伙还给小智留下了赤果果的挑衅!为了皮卡丘,也为了正义,小智和他的朋友们义不容辞的踏上了营救皮卡丘的道路. 火箭队一共有N个据点,据点之间存在M条双向道路.据点分别从1到N标号.小智一行K人从真新镇出发,营救被困在N号据点的皮卡丘.为了方便起见,我们将真新镇视为0号据点,一开始K个人都在0号点. 由于火箭队的重重布防,要想摧毁K号据点,必须

UVa10048_Audiophobia(最短路/floyd)(小白书图论专题)

解题报告 题意: 求所有路中最大分贝最小的路. 思路: 类似floyd算法的思想,u->v可以有另外一点k,通过u->k->v来走,拿u->k和k->v的最大值和u->v比较,存下最小的值. #include <iostream> #include <cstdio> #include <cstring> #include <cmath> #define inf 0x3f3f3f3f using namespace std;

POJ训练计划2253_Frogger(最短路/floyd)

解题报告 题意: 求0到1所有路中最大值最小的那个数. 思路: floyd. #include <iostream> #include <cstdio> #include <cstring> #include <cmath> #define inf 0x3f3f3f3f using namespace std; int n,m,q; double mmap[210][210]; struct node { double x,y; } p[210]; doub

UVa10099_The Tourist Guide(最短路/floyd)(小白书图论专题)

解题报告 题意: 有一个旅游团现在去出游玩,现在有n个城市,m条路.由于每一条路上面规定了最多能够通过的人数,现在想问这个旅游团人数已知的情况下最少需要运送几趟 思路: 求出发点到终点所有路当中最小值最大的那一条路. 求发可能有多种,最短路的松弛方式改掉是一种,最小生成树的解法也是一种(ps,prime和dijs就是这样子类似的) #include <iostream> #include <cstdio> #include <cstring> #include <

ACM/ICPC 之 最短路-Floyd+SPFA(BFS)+DP(ZOJ1232)

这是一道非常好的题目,融合了很多知识点. ZOJ1232-Adventrue of Super Mario 这一题折磨我挺长时间的,不过最后做出来非常开心啊,哇咔咔咔 题意就不累述了,注释有写,难点在于状态转移方程的确立和SPFA的过程 1 //最短路:Floyd+SPFA(BFS)+DP 2 //Time:20Ms Memory:336K 3 //题目很好,数据较弱,网上部分代码有些问题却能够A掉 4 //题意:超级马里奥要从A+B处背着公主以最短路程到达1处,其中1-A是村庄,剩下的是城堡

Problem B Codeforces 295B 最短路(floyd)

Description Greg has a weighed directed graph, consisting of n vertices. In this graph any pair of distinct vertices has an edge between them in both directions. Greg loves playing with the graph and now he has invented a new game: The game consists

SDUT 2929-人活着系列之芳姐和芳姐的猪(最短路Floyd)

人活着系列之芳姐和芳姐的猪 Time Limit: 1000ms   Memory limit: 65536K  有疑问?点这里^_^ 题目描述 芳姐特别喜欢猪,所以,她特意养了m个猪圈,顺便在k条无向边,每条边有都有起点v,距离.....芳姐和猪们约定好,每天去一个固定猪圈去吃饭,芳姐为了不累着她可爱的猪们,想知道所有的猪吃饭走的最短路程是多少? 输入 第一行,猪的个数m(k(1<=k<=1200).(猪的编号为1..m) N+1行N头猪所在的猪圈号第n+k+1行:u.1<=w<

hdu1874 畅通project续 最短路 floyd或dijkstra或spfa

Problem Description 某省自从实行了非常多年的畅通project计划后.最终修建了非常多路.只是路多了也不好,每次要从一个城镇到还有一个城镇时,都有很多种道路方案能够选择.而某些方案要比还有一些方案行走的距离要短非常多.这让行人非常困扰. 如今,已知起点和终点.请你计算出要从起点到终点,最短须要行走多少距离. Input 本题目包括多组数据,请处理到文件结束. 每组数据第一行包括两个正整数N和M(0< N<200,0 < M<1000),分别代表现有城镇的数目和已

最短路(floyd/dijkstra/bellmanford/spaf 模板)

floyd/dijkstra/bellmanford/spaf 模板: 1. floyd(不能处理负权环,时间复杂度为O(n^3), 空间复杂度为O(n^2)) floyd算法的本质是dp,用dp[k][i][j]表示以(1....k)为中间点,i, j之间的最短距离为多少,dp[0][i][j]即为原矩阵图. dp[k][i][j]可以由dp[k-1][i][j]转移得到,即不经过 k 点i, j之间的最短距离为多少, 也可以由dp[k-1][i][k]+dp[k-1][k][j]转移得到,即