poj 1062
题意上有一点要注意:在任何一条路径上,任何两点的等级之差都必须在限制之内。比如说:a、b、c的等级分别为3、2、1,限制为1的话。能和a、b交易就不能和c交易了,因为a和c超出限制。同样,b、c能交易就不能和a交易了,因为a、c任然超出限制。根据题意将每种物品看成每个顶点,优惠价格看成边,便构成一有向图,然后可以用Dijkstra求解。因为有等级限制,求一次Dijkstra是不行的。我看了网上大牛的思想:枚举0~L的每一种限制i,除去不在区间[rand[1]-i,rand[i]+m-i](rand[1]为酋长的等级)的顶点,然后Dijkstra,取其中最小的。
#include<iostream> #include<vector> using namespace std; #define MAX_INT 1234567890 struct edge { int v; int value; }; struct good { int price; int grade; }; good head[101]; vector <edge> map[101]; int dist[101],visit[101]; bool flag[101]; int dijkstra(int n) { int i,j,k,min; for(i=1;i<=n;i++) dist[i]=MAX_INT; for(i=0;i<map[1].size();i++) if(flag[map[1][i].v]) dist[map[1][i].v]=map[1][i].value; visit[1]=1; for(i=1;i<n;i++) { min=MAX_INT; k=0; for(j=1;j<=n;j++) if(!visit[j] && dist[j]<min) { min=dist[j]; k=j; } visit[k]=1; if(k==0) break; for(j=0;j<map[k].size();j++) { if(!visit[map[k][j].v] && flag[map[k][j].v]) { if(dist[map[k][j].v]>dist[k]+map[k][j].value) dist[map[k][j].v]=dist[k]+map[k][j].value; } } } min=MAX_INT; dist[1]=0; for(i=1;i<=n;i++) { if(min>dist[i]+head[i].price) min=dist[i]+head[i].price; } return min; } int main() { int i,j,m,n,k,gap,min; edge e; while(cin>>gap>>n) { for(i=1;i<=n;i++) { cin>>head[i].price>>head[i].grade>>m; for(j=0;j<m;j++) { cin>>e.v>>e.value; map[i].push_back(e); } } min=MAX_INT; for(i=0;i<=gap;i++) { memset(visit,0,sizeof(visit)); for(j=1;j<=n;j++) if(head[j].grade>=head[1].grade-i && head[j].grade<=head[1].grade+gap-i) flag[j]=true; else flag[j]=false; k=dijkstra(n); if(min>k) min=k; } cout<<min<<endl; for(i=1;i<=n;i++) map[i].clear(); } return 0; }
看了大牛的思想任然感觉有点模糊,所以我有用dfs做了一遍,这样做简单一点,也可以AC。
#include<iostream> #include<cstring> using namespace std; #define MAX_INT 1234567890 int edge[101][101],price[101],rank[101],visit[101],min1,n,gap; int dfs(int i,int value,int min_rank,int max_rank) { int j; visit[i]=1; min1=(min1>value+price[i])? value+price[i]:min1; for(j=1;j<=n;j++) { if(!visit[j] && edge[i][j]) { if(rank[j]<min_rank && max_rank-rank[j]<=gap) dfs(j,value+edge[i][j],rank[j],max_rank); else if(rank[j]>max_rank && rank[j]-min_rank<=gap) dfs(j,value+edge[i][j],min_rank,rank[j]); else if(rank[j]>=min_rank && rank[j]<=max_rank) dfs(j,value+edge[i][j],min_rank,max_rank); } } visit[i]=0; return 0; } int main() { int i,j,s,t,num; while(cin>>gap>>n) { for(i=1;i<=n;i++) { cin>>price[i]>>rank[i]>>num; for(j=0;j<num;j++) { cin>>s>>t; edge[i][s]=t; } } min1=MAX_INT; memset(visit,0,sizeof(visit)); dfs(1,0,rank[1],rank[1]); cout<<min1<<endl; } return 0; }