poj1062
转自:http://blog.sina.com.cn/s/blog_676070110100mjya.html
1 题意:昂贵的聘礼,好题!!! 2 算法:分两步:1、建图 2、从底到上逐个求每个点的最小费用。具体实现见程序注释。 3 #include <iostream> 4 using namespace std; 5 const int MAX=120; 6 int M,N,X,T,V; //等级限制 物品总数 替代品总数 替代品的编号 优惠价格 7 int map[MAX][MAX]; //初始化全为0 map[i][j]=-1:i和j不能交换物品 map[i][j]=t:物品i可以用物品j加t金币替换 8 int topo[MAX]; //对于处理完的图,从底向上编号 topo[i]=j:第t个物品的编号为j 9 int visted[MAX]; //访问数组,初始化为0 10 //物品结构体 11 typedef struct NODE 12 { 13 int level; //等级 14 int price; //价格 15 }NODE; 16 NODE nodes[MAX]; 17 int num=0; //物品从底向上的序号,具体Topo函数 18 //采用深度优先的方式,对物品从底向上编号 19 void Dfs(int v) 20 { 21 visted[v]=1; 22 for (int i=1;i<=N;i++) 23 { 24 // 如果i未访问过 && u、i连通 25 if (!visted[i] && map[v][i]>0) 26 { 27 Dfs(i); 28 } 29 } 30 topo[num++]=v; 31 } 32 //计算完物品的编号后,从底向上计算物品的最小花费 33 void MinCost() 34 { 35 int i,j; 36 for (i=0;i<N;i++) 37 { 38 for (j=i+1;j<N;j++) 39 { 40 //以下的关系,要画个图,看清谁指向谁 41 if (map[topo[j]][topo[i]]>0) 42 { 43 int temp=nodes[topo[i]].price+map[topo[j]][topo[i]]; 44 if ((temp<nodes[topo[j]].price)) 45 { 46 nodes[topo[j]].price=temp; 47 } 48 } 49 } 50 } 51 printf("%d\n",nodes[1].price); 52 } 53 int main() 54 { 55 int i,j; 56 memset(map,0,sizeof(map)); 57 memset(visted,0,sizeof(visted)); 58 scanf("%d%d",&M,&N); //等级限制 物品总数 59 for (i=1;i<=N;i++) 60 { 61 scanf("%d%d%d",&nodes[i].price,&nodes[i].level,&X); //价格 主人的地位等级 替代品总数 62 for (j=1;j<=X;j++) 63 { 64 scanf("%d%d",&T,&V); //替代品的编号 优惠价格 65 map[i][T]=V; 66 } 67 //如果物品i不能和物品1交换,那么物品i可以直接不考虑:即便倒贴钱,也不能和物品1交换。直接把它加入黑名单 68 if( abs(nodes[i].level-nodes[1].level) > M ) 69 { 70 //把物品i加入黑名单:置物品i不能和任何物品交换 71 for(j=1;j<N;j++) 72 { 73 map[j][i]=-1; 74 } 75 } 76 } 77 Dfs(1); //从1开始,从底向上编号 78 MinCost(); //求每个物品的最小花费 79 return 0; 80 }
自己模仿写后的代码,以及其中的一些细节和思考
1 #include <iostream> 2 #include <stdlib.h> 3 using namespace std; 4 5 struct node 6 { 7 int price; 8 int level; 9 }; 10 node a[105]; 11 int map[105][105]; 12 int m,n; 13 int visited [105]; 14 int search_result[105]; 15 int num=0; 16 17 18 void dfs(int v)//完成深度优先遍历 19 { 20 21 int i; 22 23 visited[v]=1; 24 for(i=0;i<n;i++) 25 { 26 if(visited[i]==0 && map[v][i]>0) 27 { 28 dfs(i); 29 } 30 } 31 search_result[num++]=v; 32 //cout<<"search_result[]"<<num-1<<search_result[num-1]<<endl; 33 } 34 35 36 37 int MinCost() 38 { 39 int i,j; 40 int tmp; 41 for(i=0;i<n;i++) 42 { 43 for(j=i+1;j<n;j++) 44 { 45 if(map[search_result[j]][search_result[i]]>0) 46 { 47 tmp=a[search_result[i]].price+map[search_result[j]][search_result[i]]; 48 if(tmp<a[search_result[j]].price) 49 { 50 a[search_result[j]].price=tmp; 51 } 52 53 } 54 } 55 } 56 return a[0].price; 57 } 58 int main() 59 { 60 int i,j; 61 cin>>m>>n; 62 int x; 63 int t,v; 64 for(i=0;i<n;i++)//注意这里是从一开始还是从零开始 //处理输入问题 65 { 66 cin>>a[i].price>>a[i].level>>x; 67 for(j=0;j<x;j++) 68 { 69 cin>>t>>v; 70 map[i][t-1]=v;//注意这里是t-1,主要是因为题意给的是物品从一开始编号,而我自己写的是从零开始编号 71 } 72 73 74 if(abs(a[i].level-a[0].level)>m)//这里解决等级的问题 75 { 76 for(j=0;j<n;j++)//注意这里不能改为j=i+1,因为虽有可能编号靠后,但深度搜索的时候在哪个位置不太确定 77 { 78 map[j][i]=-1; 79 } 80 } 81 } 82 dfs(0); 83 cout<<MinCost()<<endl; 84 return 0; 85 }