昂贵的聘礼
算法:分两步:1、建图 2、从底到上逐个求每个点的最小费用。具体实现见程序注释。
#include <iostream> #include<cstring> #include<cmath> using namespace std; const int MAX=120; int M,N,X,T,V; //等级限制 物品总数 替代品总数 替代品的编号 优惠价格 int map[MAX][MAX]; //初始化全为0 map[i][j]=-1:i和j不能交换物品 map[i][j]=t:物品i可以用物品j加t金币替换 int topo[MAX]; //对于处理完的图,从底向上编号 topo[i]=j:第t个物品的编号为j int visted[MAX]; //访问数组,初始化为0 //物品结构体 typedef struct NODE { int level; //等级 int price; //价格 } NODE; NODE nodes[MAX]; int num=0; //物品从底向上的序号,具体Topo函数 //采用深度优先的方式,对物品从底向上编号 void Dfs(int v) { visted[v]=1; for (int i=1; i<=N; i++) { // 如果i未访问过 && u、i连通 if (!visted[i] && map[v][i]>0) { Dfs(i); } } topo[num++]=v; } //计算完物品的编号后,从底向上计算物品的最小花费 void MinCost() { int i,j; for (i=0; i<N; i++) { for (j=i+1; j<N; j++) { //以下的关系,要画个图,看清谁指向谁 if (map[topo[j]][topo[i]]>0) { int temp=nodes[topo[i]].price+map[topo[j]][topo[i]]; if ((temp<nodes[topo[j]].price)) { nodes[topo[j]].price=temp; } } } } cout<<nodes[1].price<<endl; } int main() { int i,j; memset(map,0,sizeof(map)); memset(visted,0,sizeof(visted)); cin>>M>>N; for (i=1; i<=N; i++) { cin>>nodes[i].price>>nodes[i].level>>X; //价格 主人的地位等级 替代品总数 for (j=1; j<=X; j++) { cin>>T>>V; //替代品的编号 优惠价格 map[i][T]=V; } //如果物品i不能和物品1交换,那么物品i可以直接不考虑:即便倒贴钱,也不能和物品1交换。直接把它加入黑名单 if( abs(nodes[i].level-nodes[1].level) > M ) { //把物品i加入黑名单:置物品i不能和任何物品交换 for(j=1; j<N; j++) { map[j][i]=-1; } } } Dfs(1); //从1开始,从底向上编号 MinCost(); //求每个物品的最小花费 return 0; }
书山有路勤为径,学海无涯苦作舟!!!