https://vjudge.net/problem/UVA-10603
题意:三个杯子,倒水问题。找出最少倒水量。
思路:路径寻找问题。不难,暴力枚举。
1 #include<iostream> 2 #include<queue> 3 #include<string> 4 #include<cstring> 5 using namespace std; 6 7 int a, b, c, d; 8 int vis[205][205]; //访问变量,因为只有三个杯子,所以记录前两个杯子的状态即可 9 int cap[3]; 10 int ans[205]; 11 12 struct Node 13 { 14 int v[3], dist; 15 bool operator <(const Node& rhs) const //重载小于号 16 { 17 return dist>rhs.dist; 18 } 19 }; 20 21 void update(Node u) //每次有新状态时,记录形成d升水时需要的最少倒水量 22 { 23 for (int i = 0; i < 3; i++) 24 { 25 int x = u.v[i]; 26 if (ans[x] < 0 || u.dist < ans[x]) ans[x] = u.dist; 27 } 28 } 29 30 void bfs() 31 { 32 cap[0] = a, cap[1] = b, cap[2] = c; //记录三个杯子的容量 33 memset(vis, 0, sizeof(vis)); 34 memset(ans, -1, sizeof(ans)); 35 priority_queue<Node> q; 36 Node start; 37 start.v[0] = 0; start.v[1] = 0; start.v[2] = c; start.dist = 0; 38 q.push(start); 39 vis[0][0] = 1; //设置初始状态为已访问 40 while (!q.empty()) 41 { 42 Node p = q.top(); 43 q.pop(); 44 45 update(p); 46 if (ans[d] >= 0) break; //找到目标状态,退出循环 47 48 for (int i = 0; i < 3; i++) 49 { 50 for (int j = 0; j < 3; j++) 51 { 52 53 if (i != j && p.v[i]!=0 && p.v[j]<cap[j]) //不能给自己倒水并且第i个杯子有水和第j个杯子未满 54 { 55 Node u=p; //建立新状态 56 int r = cap[j] - p.v[j]; //计算第j个杯子空余水量 57 if (p.v[i] >= r) //如果第i个杯子水量充足 58 { 59 u.dist = p.dist + r; //更新后的倒水量 60 u.v[j] = p.v[j] + r; //更新后第j个杯子水量 61 u.v[i] = p.v[i] - r; //更新后第i个杯子水量 62 } 63 else //如果第i个杯子水量不足 64 { 65 u.dist = p.dist + p.v[i]; 66 u.v[j] = p.v[j] + p.v[i]; 67 u.v[i] = 0; 68 } 69 if(!vis[u.v[0]][u.v[1]]) //如果该状态没出现过 70 { 71 vis[u.v[0]][u.v[1]] = 1; 72 q.push(u); 73 } 74 } 75 76 77 } 78 } 79 80 } 81 82 while (d >= 0) 83 { 84 if (ans[d] >= 0) 85 { 86 cout << ans[d] << " " << d << endl; 87 return; 88 } 89 d--; //如果无法做到d升,则检验d--,找到最接近d升 90 } 91 } 92 93 int main() 94 { 95 //freopen("D:\\txt.txt","r", stdin); 96 int n; 97 cin >> n; 98 while (n--) 99 { 100 cin >> a >> b >> c >> d; 101 bfs(); 102 } 103 return 0; 104 }