HDU 1495 非常可樂 BFS/數論
阿新 • • 發佈:2017-10-25
[0 pac sca 此刻 gin 兩個 妹子 inpu urn
M - 非常可樂HDU - 1495
大家一定覺的運動以後喝可樂是一件很愜意的事情,但是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
拉著小妹子一起刷題……莫名debug了好久orz,推薦數論的解法哇,被代碼長度還有復雜度深深吸引啊有木有!雖然我不會orz……
emmmmm一開始有些蒙蔽,覺得是個數學題,然貳,大佬說,一眼就是BFS……嘛~記筆記:最少步數求解——BFS!
下面先碼BFS的解法(唔,感覺有點像是漢諾塔???漢諾塔也迷迷的orz)
先考慮一下有解的情況:這裏假設v[3]為三個杯子此刻裝有的可樂(假設v[0]>v[1]),那麽當v[0]==v[2]&&v[1]==0時,可樂被平分。
if(v[0]==v[2]&&v[0]==0) printf("%d\n",t);
無解情況就……隊列空了都沒找到滿足有解的狀態(這裏隊列實現)
每次以三個杯子裏的一個杯子為主,拿起來就往其他兩個杯子裏倒就好了,也沒有其他地方可以倒了233333
需要註意的是,這裏一直都是把v[i]的倒入v[j],處理的時候註意倒的量不要超過杯子的容量;
#include<iostream> #include<stdio.h> #include<queue> #include<string.h> using namespace std; struct node { int v[3]; int t; }; int a, b, c; int cup[3]; bool vis[105][105]; void bfs() { node d,e; queue<node>q; d.t = 0; d.v[0] = 0; d.v[1] = 0; d.v[2] = c; q.push(d); vis[0][0] = 1; while (!q.empty()) { d = q.front(); q.pop(); if (d.v[0] == d.v[2] && d.v[1] == 0) { printf("%d\n", d.t); return; } for(int i=0;i<3;i++) for (int j = 0; j < 3; j++) { if (d.v[i]==0||d.v[j] == c||i==j) continue; //因為一直都是把i倒到j裏,i不為空,j不為滿,自己不能倒給自己 int l = min(cup[j], d.v[i] + d.v[j]) - d.v[j]; memcpy(&e, &d, sizeof(d)); e.v[i] -= l; e.v[j] += l; if (!vis[e.v[0]][e.v[1]]) { vis[e.v[0]][e.v[1]] = 1; e.t ++; q.push(e); } } } puts("NO"); } int main() { while (scanf("%d%d%d", &c, &a, &b)!=EOF) { if (a==0 || b==0 || c==0) break; memset(vis, 0, sizeof(vis)); cup[0] = max(a, b); cup[1] = min(a, b); cup[2] = c; bfs(); } return 0; }
數論 ……待續
HDU 1495 非常可樂 BFS/數論