poj1062(昂贵的聘礼)
题目大意:
中文题目不用翻译。
说下通俗的题意:M代表等级的权限限制,N代表有N个地方,其中酋长地方的编号永远是第一个编号,所以输入的第一组数据就是酋长的允诺编号为1. 接着有X行能与此地方交换物品和拥有替代品之后的价格。其中P代表这个地方的价值,L代表这个地方的等级。问你怎么用自己的聪明才智使得到达编号1 这个地方的花费最少。
测试实例的走法: 4->2->1 一共花费5250.
解题思路:
建图,dijstra最短路。看懂数据建图即可,从1->n,然后可以可以把年轻的探险家从0开始走到“1”这个地方花费的最小价格。 这个用dijstra 注意的一点就是记得等级限制,控制好等级限制即可。
注意:1.“另外他要告诉你的是,在这个部落里,等级观念十分森严。地位差距超过一定限制的两个人之间不会进行任何形式的直接接触,包括交易。 ” 这句话我觉得本身说的就不太对,刚开始我一直认为 是:节点->节点的差距限制不超过等级 就Ok了,可是这句话的意思是年轻的探险家走过的最短路径,最小的等级和最大的等级限制这个差距不超过M。 这时就需要把所有数据L[1]-M到L[1]+M。这个所有的差距为M的等级枚举一遍。因为假如你不枚举,所产生的路径的等级可能在L[1]-m到L[1]之间,也可能在L[1]到L[1]+m之间得到最小的路径,也可能在别的区间,所以需要枚举所有区间为M 的等级(但在这个区间里必须包括L[1]这个节点的等级)。
2.“但是如果他和某个地位较低的人进行了交易,地位较高的的人不会再和他交易,他们认为这样等于是间接接触,反过来也一样。” 这句话一点用也没有。 本身以为:假如等级的路径:4-3-4. 这时候等级的限制距离为2时,这种路径是可以的。并不是它说的从等级四到等级三,再之后不能从等级三到等级四。
3.最后一点注意:这个图是有向图,WA了那么多,discuss数据全过了,这是看自己建图有没有建成了无向图。 这个点也是我在discuss看到的,我是有多菜。
写了这么多注意,可能是我自己的读题有问题吧。 大家不要在意。
我的代码还是很简单的,就是弄清楚为啥需要枚举区间即可,然后典型dijstra最短路算出每次枚举的需要的花费,最后枚举过后输出最少的花费。
代码:
1 #include <algorithm> 2 #include <iostream> 3 #include <sstream> 4 #include <cstdlib> 5 #include <cstring> 6 #include <cstdio> 7 #include <string> 8 #include <bitset> 9 #include <vector> 10 #include <queue> 11 #include <stack> 12 #include <cmath> 13 #include <list> 14 //#include <map> 15 #include <set> 16 using namespace std; 17 /***************************************/ 18 #define ll long long 19 #define int64 __int64 20 /***************************************/ 21 const int INF = 0x7f7f7f7f; 22 const double eps = 1e-8; 23 const double PIE=acos(-1.0); 24 const int d1x[]= {0,-1,0,1}; 25 const int d1y[]= {-1,0,1,0}; 26 const int d2x[]= {0,-1,0,1}; 27 const int d2y[]= {1,0,-1,0}; 28 const int fx[]= {-1,-1,-1,0,0,1,1,1}; 29 const int fy[]= {-1,0,1,-1,1,-1,0,1}; 30 /***************************************/ 31 void openfile() 32 { 33 freopen("data.in","rb",stdin); 34 freopen("data.out","wb",stdout); 35 } 36 /**********************华丽丽的分割线,以上为模板部分*****************/ 37 int lowcost[100],level[100]; //到此地方的最少花费、此地方的等级 38 int vis[100]; 39 int map[100][100]; 40 int min1; 41 void dijstra(int m,int n) 42 { 43 int i,j,k; 44 int min; 45 min1=INF; 46 for(int lev=level[1]-m; lev<=level[1]; lev++) //枚举等级区间 47 { 48 for(i=1; i<=n; i++) 49 { 50 lowcost[i]=map[0][i]; 51 vis[i]=0; 52 } 53 int sum=0; 54 for (j=1; j<=n; j++) 55 if (level[j]<lev||level[j]>lev+m) //把不再此等级范围内的地方标记 56 { 57 vis[j]=1; 58 sum++; 59 } 60 for(i=1; i<=n-1-sum; i++) 61 { 62 j=0; 63 min=INF; 64 for(k=1; k<=n; k++) 65 { 66 if (!vis[k]&&lowcost[k]<min) 67 { 68 min=lowcost[k]; 69 j=k; 70 } 71 } 72 vis[j]=1; 73 for(k=1; k<=n; k++) 74 if (!vis[k]&&(map[j][k]+lowcost[j]<lowcost[k])) 75 lowcost[k]=map[j][k]+lowcost[j]; 76 } 77 if (lowcost[1]<min1) 78 min1=lowcost[1]; 79 } 80 } 81 int main() 82 { 83 int m,n; 84 while(scanf("%d%d",&m,&n)!=EOF) 85 { 86 int i,j; 87 for(i=0; i<=n; i++) 88 for(j=0; j<=n; j++) 89 map[i][j]=INF; 90 for(i=1; i<=n; i++) 91 { 92 int a,b,c; 93 scanf("%d%d%d",&a,&b,&c); 94 level[i]=b; 95 map[0][i]=a; 96 for(j=0; j<c; j++) 97 { 98 int x,val; 99 scanf("%d%d",&x,&val); 100 if (map[i][x]>val) //有向图 101 { 102 // map[i][x]=val; 103 map[x][i]=val; 104 } 105 } 106 } 107 dijstra(m,n); 108 printf("%d\n",min1); 109 } 110 return 0; 111 }