[POJ 1062] 昂贵的聘礼【Dijkstra】
Problem:
Time Limit: 1000MS | Memory Limit: 10000K |
Description
为了方便起见,我们把所有的物品从1开始进行编号,酋长的允诺也看作一个物品,并且编号总是1。每个物品都有对应的价格P,主人的地位等级L,以及一系列的替代品Ti和该替代品所对应的"优惠"Vi。如果两人地位等级差距超过了M,就不能"间接交易"。你必须根据这些数据来计算出探险家最少需要多少金币才能娶到酋长的女儿。
Input
Output
Sample Input
1 4 10000 3 2 2 8000 3 5000 1000 2 1 4 200 3000 2 1 4 200 50 2 0
Sample Output
5250
Source
Solution:
##说句题外话,难得在 POJ 上碰到一道中文题,而且又是一道很好的图论题。##
将物品 1 作为终点,并创建一个虚拟节点“物品 0”作为起点,表示初始状态。
对于每个价格为 P 的物品 i,从 0 -> i 连一条权值为 P 的边,表示从初始状态到拥有物品 i 需要花费 P 个金币。
对于物品 i 的每个价格为 V 的替代品 T,从 T -> i 连一条权值为 V 的边,表示从拥有物品 T 到换得 i 需要花费 V 个金币。
由于等级限制,每次枚举一个物品的主人等级 L,限定只与等级在 L ~ L+M 范围内的人交易,跑 Dijkstra 即可。
Code: O(n3) [192K, 16MS]
#include<cstdio> #include<cstdlib> #include<cstring> #include<cmath> #include<iostream> #include<algorithm> using namespace std; int M, N, ans; struct Edge{ int np, val; Edge *nxt; }; struct Graph{ Edge *V[105], E[10105]; int L[105], tope; inline void clear() {tope = 0, memset(V, 0, sizeof(V));} inline void addedge(int u, int v, int w){ E[++tope].np = v, E[tope].val = w; E[tope].nxt = V[u], V[u] = &E[tope]; } } G; bool tried[105]; int cost[105]; bool vis[105]; inline int Dijkstra(){ memset(cost, 0x3f, sizeof(cost)), cost[0] = 0; memset(vis, 0, sizeof(vis)); for(register int i = 0; i <= N; i++){ int mincost = 101; // Use an empty number as the beginning of the comparation for(register int j = 0; j <= N; j++) if(!vis[j] && G.L[j] - G.L[0] <= M && cost[j] < cost[mincost]) mincost = j; vis[mincost] = 1; // Find a object with minimum cost if(mincost == 1) return cost[1]; // The explorer finds out the amount of dowry for(register Edge *ne = G.V[mincost]; ne; ne = ne->nxt) if(G.L[ne->np] >= G.L[0] && G.L[ne->np] - G.L[0] <= M) cost[ne->np] = min(cost[ne->np], cost[mincost] + ne->val); // Update the cost } return 0x3f3f3f3f; } int main(){ while(scanf("%d%d", &M, &N) != EOF){ G.clear(); for(register int i = 1; i <= N; i++){ int P, X, T; scanf("%d%d%d", &P, &G.L[i], &X); G.addedge(0, i, P); // Buy this object directly for(register int j = 1; j <= X; j++){ scanf("%d%d", &T, &P); G.addedge(T, i, P); // Use surrenal to lower the price } } memset(tried, 0, sizeof(tried)), ans = 0x3f3f3f3f; for(register int i = 1; i <= N; i++){ // Try to pretend as each level of the owners if(tried[G.L[i]] || abs(G.L[i] - G.L[1]) > M) continue; tried[G.L[0] = G.L[i]] = 1; ans = min(ans, Dijkstra()); } printf("%d\n", ans); } return 0; }
发表评论