http://poj.org/problem?id=1062

dijstra+枚举法,,,

题意中文不再说明了,,,,,

解法:求一点到其他所有点的最短路径(还要加上终点的pri[],在一条路径上点与点之间的等级差不能超过n,

扫描区间因为每条路径都要经过点1,所以依次扫描区间[ lev[1]-n , leve[1] ]......[ lev[1] , lev[1]+n ]

代码:

#include<iostream>
#include<algorithm>
#include<string.h>
#define N 1001
#define M 111111111
using namespace std;
int map[N][N],G[N][N],dis[N],lev[N],pre[N];
int n,m,k;
bool visit[N];
void dijstra(int a)
{  memset(visit,false,sizeof(visit));
    for(int i=1;i<=m;++i) dis[i]=(a==i?0:M);
     for(int i=1;i<=m;++i)
     {  int minx=M;
        for(int j=1;j<=m;++j)
        if(!visit[j]&&minx>dis[j])
          minx=dis[a=j];
          visit[a]=true;
           for(int j=1;j<=m;++j)
            if(!visit[j])
            dis[j]=min(dis[j],dis[a]+map[a][j]);
     }
     }
    void sift(int l,int r)//扫描两端的等级不在1-r上的把它赋为M。
    {   for(int i=1;i<=m;++i)
         for(int j=1;j<=m;++j)
         if(lev[i]>=l&&lev[i]<=r&&lev[j]>=l&&lev[j]<=r) map[i][j]=G[i][j];
         else  map[i][j]=M;
    }
    int pro()
    {    int minx=M;
        for(int i=lev[1]-n;i<=lev[1];++i)
         {   sift(i,i+n);//依次扫描。
             dijstra(1);
               for(int j=1;j<=m;++j)
               minx=min(minx,dis[j]+pre[j]);
         }
         return minx;
        }
int main()
    {   cin>>n>>m;
      for(int i=0;i<=m;i++)
	   for(int j=0;j<=m;j++)
	   {
		   G[i][j]=M;
		   map[i][j]=M;
	   }
        for(int i=1;i<=m;++i)
        {       cin>>pre[i]>>lev[i]>>k;
             for(int j=1;j<=k;++j)
              {      int a,b;
                     cin>>a>>b;
                     G[i][a]=b;
              }
             }
             cout<<pro()<<endl;
             return 0;
             //system("pause");
        }



你可能感兴趣的:(http://poj.org/problem?id=1062)