UVA 10603 - Fill(dijkstra + 状态图)
生活随笔
收集整理的這篇文章主要介紹了
UVA 10603 - Fill(dijkstra + 状态图)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
題目鏈接
https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=1544
題目大意
有三個水杯,容量分別為 a, b, c 剛開始 c 水杯注滿水,其他是空的,然后求經過 n 次操作后可不可以得到 d 升水。如果可以的話,轉移的水量盡量少,如果無法得到 d 升的話,就輸出 d’ 升,d’< d 并且 d’ 盡量的大。
這里的轉移水量指,總共轉移了多少升水,比如 a 向 b 注了五升水,那么轉移水量為五升。
解題過程
照著紫書示例敲得,看作者代碼學到了好多東西。
題目分析
首先是進行枚舉操作的時候,雖然總共三個杯子,作者還是把數據放到了數組里面,簡化不少代碼,如果是我的話,就直接寫9個if了。
然后是代碼的思想是 dijkstra,求最短路。
- 把整個問題當做一個狀態圖,每個點由三個水杯里面的水確定。
- 兩個點之間的邊的權值,是由兩個狀態轉化所需要轉移的水量。(注意一點是這里是有向圖)
- 另外三個水杯里面的水合不變,給定兩個水杯里水的體積,就可以確定另一個,所以儲存狀態時,只需要記錄兩個水杯的體積即可。
經過上面的解析,這個問題就抽象成了,求一個有向圖的最短路徑,然后使用了優先隊列優化的 dijkstra 。
另外memcpy的使用值得一學,使用方法如下:
memset(&a, &b, sizeof(a));
把 b 復制給a,直接復制的內存,效率比直接循環快。
AC代碼
#include<bits/stdc++.h> using namespace std;const int MAX = 200+10;struct Node {int v[3], dist; };bool operator < (const struct Node& a, const struct Node& b) {return a.dist > b.dist; }int vis[MAX][MAX], ans[MAX];void update_ans(Node u) {for (int i = 0; i < 3; i++){int d = u.v[i];if (ans[d] < 0 || ans[d] > u.dist)ans[d] = u.dist;} }void solve(int a, int b, int c, int d) {int cap[3] = {a,b,c};memset(vis, 0, sizeof(vis));memset(ans, -1, sizeof(ans));Node start;start.v[0] = 0, start.v[1] = 0, start.v[2] = c;start.dist = 0;priority_queue<Node> q;q.push(start);vis[0][0] = 1;while (!q.empty()){Node u = q.top(); q.pop();update_ans(u);if (ans[d] >= 0)break;for (int i = 0; i < 3; i++){for (int j = 0; j < 3; j++){if (i == j)continue;if (u.v[i] == 0 || u.v[j] == cap[j])continue;int amount = min(cap[j], u.v[i] + u.v[j]) - u.v[j];Node u2;memcpy(&u2, &u, sizeof(u));u2.dist = u.dist + amount;u2.v[i] -= amount;u2.v[j] += amount;if (!vis[u2.v[1]][u2.v[0]]){vis[u2.v[1]][u2.v[0]] = 1;q.push(u2);}}}} }int main() {int T;scanf("%d", &T);while (T--){int a, b, c, d;scanf("%d %d %d %d", &a, &b, &c, &d);solve(a, b, c, d);while (d >= 0){if (ans[d] >= 0){printf("%d %d\n", ans[d], d);break;}d--;}} }
轉載于:https://www.cnblogs.com/ACMFish/p/7222860.html
總結
以上是生活随笔為你收集整理的UVA 10603 - Fill(dijkstra + 状态图)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: ConcurrentModificati
- 下一篇: 枚举进程再来两弹