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"); }