这是我的第一题dijkstra,开始我还是不会把题目的要求转换为要实际的模型,还是看了mengxm的这篇题解,才有了真正的认识,而且他的代码非常简洁,看起来很舒服,学习了!在此次谢谢他。
这题的关键是要有等级的限制,即不能超过等级限制的范围,因此在这里我们可以用一个abs(a-b)<=m来判断是否超出范围,超出了就不考虑了。边的权值就是优惠的值,而最后要求的min_cost则是所有边的和加上最后一个节点的值。其它的就直接套Dijkstra算法就OK了~ 呼呼~
#include <iostream> #include <fstream> using namespace std; #define LEN 110 const int INF (1<<30); #define MAX(a,b) (a>b?a:b) #define MIN(a,b) (a<b?a:b) #define ABS(a) (a<0?-a:a) #define LEV_TEST(a,b) (ABS(a-b)<=M?true:false) //判断是否满足等级差 int M; //等级差距限制 int N; //物品数量 int dist[LEN]; //每一点的cost,即边权值之和,不包括节点的price,初始点1的dist为0 int map[LEN][LEN]; int max_lev[LEN],min_lev[LEN]; int min_cost; //记录最小cost的值,即最后的结果 bool v[LEN]; struct Node{ int price; int level; int num; }node[LEN]; void Dijkstra() { int i,j,min,min_pos=0; for(i=1; i<=N; i++) { min=INF; for(j=1; j<=N; j++) //每次寻找最小的值 { if(dist[j]<min && !v[j] && LEV_TEST(max_lev[j],min_lev[j]) ) { min=dist[j]; min_pos=j; } } v[min_pos]=true; min_cost=MIN(min_cost,dist[min_pos]+node[min_pos].price); //最小值为边的和+最后一个节点的price for(j=1; j<=N; j++) { if(!v[j] && map[min_pos][j]!=-1 && dist[j]>dist[min_pos]+map[min_pos][j]) { dist[j]=dist[min_pos]+map[min_pos][j]; max_lev[j]=MAX(node[j].level,max_lev[min_pos]); //更新到达路径的max_lev min_lev[j]=MIN(node[j].level,min_lev[min_pos]); } } } } int main() { int i,j,k; freopen("acm.txt","r",stdin); while(scanf("%d%d",&M,&N)!=EOF) { memset(map,-1,sizeof(map)); memset(v,false,sizeof(v)); for(i=1; i<=N; i++) { dist[i]=INF; } k=0; for(i=1; i<=N; i++) { scanf("%d%d%d",&node[i].price,&node[i].level,&node[i].num); for(j=1; j<=node[i].num; j++) { int to,pri; scanf("%d%d",&to,&pri); map[i][to]=pri; //i->to边的cost } } max_lev[1]=min_lev[1]=node[1].level; dist[1]=0; min_cost=node[1].price; Dijkstra(); printf("%d\n",min_cost); } return 0; }