1. 程式人生 > >HDU 1495 非常可樂【BFS】

HDU 1495 非常可樂【BFS】

esp style 模擬操作 pop ace nbsp urn 而且 ane

題目鏈接:https://vjudge.net/problem/HDU-1495

轉載於:https://www.cnblogs.com/ECJTUACM-873284962/p/6750320.html

題目大意:

大家一定覺的運動以後喝可樂是一件很愜意的事情,但是seeyou卻不這麽認為。因為每次當seeyou買了可樂以後,阿牛就要求和seeyou一起分享這一瓶可樂,而且一定要喝的和seeyou一樣多。但seeyou的手中只有兩個杯子,它們的容量分別是N 毫升和M 毫升 可樂的體積為S (S<101)毫升 (正好裝滿一瓶) ,它們三個之間可以相互倒可樂 (都是沒有刻度的,且 S==N+M,101>S>0,N>0,M>0) 。聰明的ACMER你們說他們能平分嗎?如果能請輸出倒可樂的最少的次數,如果不能輸出"NO"。

Input

三個整數 : S 可樂的體積 , N 和 M是兩個杯子的容量,以"0 0 0"結束。

Output

如果能平分的話請輸出最少要倒的次數,否則輸出"NO"。

Sample Input

7 4 3
4 1 3
0 0 0

Sample Output

NO
3

解題分析:
求倒水的最少步數,很明顯要用bfs做,一旦找到符合條件的,就可以退出搜索,此時的步數即為所求。同時,由於搜索時,這三個瓶子要相互進行倒水的模擬操作,所以用v[]數組分別表示s,n,m比較方便,因為這時可以
用循環來簡化操作,而不是分六種情況分別進行討論。

#include<cstdio>
#include<cstring>
#include
<queue> using namespace std; int v[5]; int sign[110][110][100]; struct cup//記錄遍歷中3個水杯容藏可樂情況 { int v[5]; int step; }temp; void pour(int a, int b)//倒水函數,把a杯子中的可樂倒到b杯子中 { int sum = temp.v[a] + temp.v[b]; if (sum >= v[b]) temp.v[b] = v[b]; else temp.v[b] = sum; temp.v[a]
= sum - temp.v[b]; } void bfs() { int i, j; queue<cup>q; cup cnt; cnt.v[1] = v[1];cnt.v[2] = 0; cnt.v[3] = 0;cnt.step = 0; q.push(cnt); memset(sign, 0, sizeof(sign)); sign[v[1]][0][0] = 1; while (!q.empty()) { cnt = q.front(); q.pop(); if (cnt.v[1] == cnt.v[3] && cnt.v[2] == 0) //v[3]>v[2],最後的一半水一定在v[1]和v[3]中,若v[3]==v[2],則也同樣存在最後的一半水在v[1]和v[3]中的情況 { printf("%d\n", cnt.step); return; } for (i = 1; i<4; ++i) { for (j = 1; j<4; ++j) { if (i != j)//自己不倒水給自己 { temp = cnt;//每個水位情況都要把所有操作枚舉一遍,所以都要賦值為原始水位情況,即不能改變cnt的值,否則會對後面的循環造成影響 pour(i, j); if (!sign[temp.v[1]][temp.v[2]][temp.v[3]]) { temp.step++; q.push(temp); sign[temp.v[1]][temp.v[2]][temp.v[3]] = 1; } } } } } printf("NO\n"); } int main() { while (scanf("%d%d%d", &v[1], &v[2], &v[3]) && v[1] || v[2] || v[3]) { if (v[1] % 2 != 0 && v[2] != v[3]) //如果s的容量為奇數,且n!=m的容量,此時一定不可能滿足要求,直接退出 { printf("NO\n"); continue; } if (v[2]>v[3]) { int t = v[2]; v[2] = v[3]; v[3] = t; } bfs(); } return 0; }


2018-05-26

HDU 1495 非常可樂【BFS】