51nod 1459 迷宫游戏(迪杰特斯拉Dijkstra算法)

题目:

你来到一个迷宫前。该迷宫由若干个房间组成,每个房间都有一个得分,第一次进入这个房间,你就可以得到这个分数。还有若干双向道路连结这些房间,你沿着这些道路从一个房间走到另外一个房间需要一些时间。游戏规定了你的起点和终点房间,你首要目标是从起点尽快到达终点,在满足首要目标的前提下,使得你的得分总和尽可能大。现在问题来了,给定房间、道路、分数、起点和终点等全部信息,你能计算在尽快离开迷宫的前提下,你的最大得分是多少么?
Input
第一行4个整数n (<=500), m, start, end。n表示房间的个数,房间编号从0到(n - 1),m表示道路数,任意两个房间之间最多只有一条道路,start和end表示起点和终点房间的编号。
第二行包含n个空格分隔的正整数(不超过600),表示进入每个房间你的得分。
再接下来m行,每行3个空格分隔的整数x, y, z (0<z<=200)表示道路,表示从房间x到房间y(双向)的道路,注意,最多只有一条道路连结两个房间, 你需要的时间为z。
输入保证从start到end至少有一条路径。
Output
一行,两个空格分隔的整数,第一个表示你最少需要的时间,第二个表示你在最少时间前提下可以获得的最大得分。
Input示例
3 2 0 2
1 2 3
0 1 10
1 2 11
Output示例
21 6

这个是51nod的第一道基础题,还算是比较水的,我不是菊苣啊,但是我想说一下我的意见,就是一般的ACMer不要看不起基础题啊!我一开始就是抱着“啊你们都是基础题一群乌合之众劳资就是拿你们练手速的看劳资秒了你们!”的态度打开了基础题,然后等我做的时候就傻眼了,题目倒是确实挺基础的恩,但问题是有些算法我不会呀啊啊啊啊!T0T!反正本人是用了3天时间才撸完了基础题,中间实在想不出的两三道题还看了下别人菊苣的博客,辣鸡得抠脚啊!所以推荐大家还是把基础题全部补完,这样可以补牢自己的基本功^0^。


好了,废话不多说了。让我们来正式看看这道题吧。

本题的思路就是用Dijkstra算法求最短路,只不过多了一个在满足最短路的情况下,使得分最大,easy,只要用一个sum数组把得分存起来就行了,搜索的时候,如果路径权值相同的话,就比较哪条路径的权值大,如果新加上路的话就把那个房间的分数加在sum上就可以了。好了,直接上代码吧,这题目还是比较水的~= ̄ω ̄=。

#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
#define maxx 999999
int map[501][501];
int n,m,st,en,f[501],mark[501],sum[501],a[501];
void Dijkstra()
{
   int i,j,k,min;
   memset(mark,0,sizeof(mark));
   sum[st]=a[st];
   for(i=0;i<n;i++)
   {
       f[i]=map[st][i];
   }
   f[st]=0;
   for(i=0;i<n;i++)
   {
       min=maxx;
       for(j=0;j<n;j++)//找出第i个离起点最近的距离,找到后把此点标记为k,mark[k]=1,表示要走这段路了,以后不再找了 
       {
           if(!mark[j]&&f[j]<min)
           {
               min=f[j];
               k=j;
           }
       }
       if(min==maxx)break;//没路了就跳出 
       mark[k]=1;
       for(j=0;j<n;j++)
       {
           if(!mark[j]&&f[j]>=f[k]+map[k][j])
		   {
		   	//	printf("%d %d %d %d %d %d\n",i,j,k,f[j],f[k],map[k][j]);
		   	   if(f[j]==f[k]+map[k][j])
		   	   {
		   	   		sum[j]=max(sum[j],sum[k]+a[j]);  
		   	   }
		   	   else
		   	   {
              	    f[j]=f[k]+map[k][j];
              	    sum[j]=sum[k]+a[j];
               }
           }
       }
   }
   if(f[en]!=maxx)printf("%d %d\n",f[en],sum[en]);
   else printf("-1\n");
}
int main()
{
    int x,y,z,i,j;
    while(scanf("%d%d%d%d",&n,&m,&st,&en)!=EOF)
    {
        for(i=0;i<=n-1;i++)
            for(j=0;j<=n-1;j++)
                map[i][j]=maxx;//map[i][j]表示从i到j所要花费的距离 
        for(i=0;i<n;i++)
        {
       		scanf("%d",&a[i]);
        }
        for(i=1;i<=m;i++)
        {
            scanf("%d %d %d",&x,&y,&z);
            if(map[x][y]>z)
            {map[x][y]=map[y][x]=z;}
        }
        Dijkstra();
    }
    return 0;
}





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值