POJ1062 昂贵的聘礼 Dijkstra算法

分析:Dijkstra算法。这道题的难点在于每一条路径上都要满足等级限制,即如果等级限制为1,你和等级为3的人交换之后再和等级为2的人交换,那么你将不能再和等级为4的人交换了,因为4-2=2>1;同理你要是先和等级为4的人交换了,那么就不能和等级为2的人交换了。弄清楚了这点就没什么大问题了。

酋长要的东西的编号恒为1,但题中并没有给出终点在哪里,既然这样,我们就把编号为1的点作为终点,至于起点呢,我们枚举每一个顶点,这样做的好处就是:我们可以顺便解决等级限制的问题。我们把枚举的当前点作为起点,同时作为等级最高的点(也可以作为等级最低的点,这都无所谓,我们的目的是要找出一个单方向比较等级的量度),然后可以筛选出等级限制范围内的点:再次遍历每一个点,如果某点的等级比当前点高,或者是和当前点的等级差在限制范围之外,那么我们可以标记s数组为标记状态,这样在进行Dijkstra算法的过程中就不会再遍历这点了。然后再当前等级限制状态下找出所需的最小金币,最后再找出每种情况下最小金币中的最小值输出就行了。


实现代码如下:

#include <iostream>
#include <cstdio>
#include <cmath>
using namespace std;
#define INF 999999999
int map[110][110];
int n,m;
int w[110];
bool s[110];
int Dijkstra()
{
    for(int i=1;i<=n;i++)
      w[i]=map[0][i];
    for(int i=1;i<=n;i++)
    {
        int tmp=INF;
        int u=0;
        for(int j=1;j<=n;j++)
          if(!s[j]&&w[j]<tmp)
          {
              tmp=w[j];
              u=j;
          }
        if(u==0) break;
        s[u]=true;
        for(int j=1;j<=n;j++)
          if(!s[j]&&map[u][j]>0)
            if(w[j]>w[u]+map[u][j])
              w[j]=w[u]+map[u][j];
    }
    return w[1];
}
int main()
{
    int lev;
    int l[110],x;
    int t,v;
    for(int i=0;i<=n;i++)
      for(int j=0;j<=n;j++)
        map[i][j]=INF;
    scanf("%d%d",&lev,&n);
    for(int i=1;i<=n;i++)
    {
        scanf("%d%d%d",&map[0][i],&l[i],&x);
        for(int j=1;j<=x;j++)
        {
            scanf("%d%d",&t,&v);
            map[t][i]=v;
        }
    }
    int ans=INF;
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=n;j++)
          if(l[i]<l[j]||l[i]-l[j]>lev) s[j]=true;
          else s[j]=false;
        int tmp=Dijkstra();
        if(tmp<ans) ans=tmp;
    }
    printf("%d\n",ans);
    return 0;
}


你可能感兴趣的:(POJ1062 昂贵的聘礼 Dijkstra算法)