POJ - 1062 昂贵的聘礼
題目鏈接
Description
年輕的探險家來到了一個印第安部落里。在那里他和酋長的女兒相愛了,于是便向酋長去求親。酋長要他用10000個金幣作為聘禮才答應把女兒嫁給他。探險家拿不出這么多金幣,便請求酋長降低要求。酋長說:”嗯,如果你能夠替我弄到大祭司的皮襖,我可以只要8000金幣。如果你能夠弄來他的水晶球,那么只要5000金幣就行了。”探險家就跑到大祭司那里,向他要求皮襖或水晶球,大祭司要他用金幣來換,或者替他弄來其他的東西,他可以降低價格。探險家于是又跑到其他地方,其他人也提出了類似的要求,或者直接用金幣換,或者找到其他東西就可以降低價格。不過探險家沒必要用多樣東西去換一樣東西,因為不會得到更低的價格。探險家現在很需要你的幫忙,讓他用最少的金幣娶到自己的心上人。另外他要告訴你的是,在這個部落里,等級觀念十分森嚴。地位差距超過一定限制的兩個人之間不會進行任何形式的直接接觸,包括交易。他是一個外來人,所以可以不受這些限制。但是如果他和某個地位較低的人進行了交易,地位較高的的人不會再和他交易,他們認為這樣等于是間接接觸,反過來也一樣。因此你需要在考慮所有的情況以后給他提供一個最好的方案。
為了方便起見,我們把所有的物品從1開始進行編號,酋長的允諾也看作一個物品,并且編號總是1。每個物品都有對應的價格P,主人的地位等級L,以及一系列的替代品Ti和該替代品所對應的”優惠”Vi。如果兩人地位等級差距超過了M,就不能”間接交易”。你必須根據這些數據來計算出探險家最少需要多少金幣才能娶到酋長的女兒。
Input
輸入第一行是兩個整數M,N(1 <= N <= 100),依次表示地位等級差距限制和物品的總數。接下來按照編號從小到大依次給出了N個物品的描述。每個物品的描述開頭是三個非負整數P、L、X(X < N),依次表示該物品的價格、主人的地位等級和替代品總數。接下來X行每行包括兩個整數T和V,分別表示替代品的編號和”優惠價格”。
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
思路
- 數據小可用dfs,枚舉每一個狀態
- 構建Dijkstra,關鍵是解決:交易群體的等級差小于M,這里用模擬區間的辦法解決,應為最終都是到1,所以枚舉[ level[1] - M, level[1] ] ~~ [ level[1], level[1] + M ]
AC
// Dijkstra // #include <bits/stdc++.h> #include <iostream> #include <stdio.h> #include <string.h> #include <cmath> #include <vector> #define mem(a, b) memset(a, b, sizeof(a)) #define P pair<int, int> #define N 105 using namespace std; int inf = 0x3f3f3f3f; int n, m, vis[N], dis[N], price[N], level[N]; vector<P> ve[N]; int Dijkstra(int x, int min_l, int max_l) {mem(dis, inf);mem(vis, 0);dis[1] = 0;for (int i = 1; i <= n; i++) {int MIN = inf, u = -1;for (int j = 1; j <= n; j++) {if (vis[j] || level[j] < min_l || level[j] > max_l)continue;if (MIN > dis[j]) {MIN = dis[j];u = j;}}if (u == -1)break;vis[u] = 1;for (int j = 0; j < int(ve[u].size()); j++) {P t = ve[u][j];if (vis[t.first] || level[t.first] < min_l || level[t.first] > max_l)continue;if (dis[t.first] > MIN + t.second) {dis[t.first] = MIN + t.second;}}}int ans = inf;for (int i = 1; i <= n; i++) {if (price[i] + dis[i] < ans) {ans = price[i] + dis[i];}}return ans; } int main(){// freopen("in.txt", "r", stdin);scanf("%d%d", &m, &n);for (int i = 1; i <= n; i++) {int x;scanf("%d%d%d", &price[i], &level[i], &x);for (int j = 0; j < x; j++) {int a, b;scanf("%d%d", &a, &b);ve[i].push_back(make_pair(a, b));}}int ans = inf;for (int i = 0; i <= m; i++) {int temp = Dijkstra(1, level[1] - m + i, level[1] + i);ans = min(temp, ans);}printf("%d\n", ans);return 0; } // dfs // #include <bits/stdc++.h> #include <iostream> #include <stdio.h> #include <string.h> #include <cmath> #include <vector> #define mem(a, b) memset(a, b, sizeof(a)) #define P pair<int, int> #define N 105 using namespace std; int inf = 0x3f3f3f3f; struct ac{int d, l, num; }stuff[N]; int vis[N], n, m; vector<ac> ve[N]; int ans = 0; void solve(int x, int min_l, int max_l, int sum) {// printf("x = %d, min_l = %d, max_l = %d, sum = %d, ans = %d\n", x, min_l, max_l, sum, ans);if (ans > sum + stuff[x].d) ans = sum + stuff[x].d;for (int i = 0; i < int(ve[x].size()); i++) {ac t = ve[x][i];int min_ll = min(min_l, stuff[t.num].l);int max_ll = max(max_l, stuff[t.num].l);if (!vis[t.num] && max_ll - min_ll <= m) {vis[t.num] = 1;solve(t.num, min_ll, max_ll, sum + t.d);vis[t.num] = 0;}} }int main(){// freopen("in.txt", "r", stdin);scanf("%d%d", &m, &n);for (int i = 1; i <= n; i++) {int x;scanf("%d%d%d", &stuff[i].d, &stuff[i].l, &x);for (int j = 0; j < x; j++) {ac t;scanf("%d%d", &t.num, &t.d);ve[i].push_back(t);}}mem(vis, 0);vis[1] = 1;ans = inf;solve(1, stuff[1].l, stuff[1].l, 0);printf("%d\n", ans);return 0; }總結
以上是生活随笔為你收集整理的POJ - 1062 昂贵的聘礼的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 网络流 (EK Dinic)
- 下一篇: python - 定时拍照并发送到qq