HDU1495 非常可樂(兩種解法)
阿新 • • 發佈:2021-01-20
題目連結:https://vjudge.net/problem/HDU-1495
Description
大家一定覺的運動以後喝可樂是一件很愜意的事情,但是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
解題思路一:數論解法,證明可見:https://blog.csdn.net/xiaolonggezte/article/details/70795894
Cpp Code
#include<bits/stdc++.h> using namespace std; int main() { int a,b,c; while( ~ scanf("%d%d%d",&a,&b,&c)) { if(a == 0 && b == 0 && c == 0) break; int g = __gcd(b,c); if((b + c) / g % 2) { cout << "NO" << endl; continue; } cout << (b + c) / g - 1 << endl; } return 0; }
解題思路二:開始的時候,所有可樂在s中,2個杯子n和m都空著。過程中,可以將任何1個容器中的可樂倒到另外某個容器中,或將目標容器倒滿,或將源容器倒空。因為容器沒有刻度,只能這樣。這個過程中,如果出現某個容器空,另外2個容器可樂相同則成功。如果開始的時候,可樂的容量是奇數,則不可能平分可樂。容器間可樂倒來倒去,每次有6種倒法,對這6種倒法進行試探即可。求的是最少倒的次數,所以可以用BFS實現。
Cpp Code
#include<iostream> #include<algorithm> #include<cstring> #include<cmath> #include<queue> using namespace std; const int maxn = 110; struct Status{ int s, a, b, t; } st; bool vis[maxn][maxn]; int s, a, b; int bfs(){ queue<Status> q; memset(vis, 0, sizeof(vis)); st.a = 0; st.b = 0; st.s = s; st.t = 0; vis[a][b] = 1; q.push(st); while (!q.empty()) { Status v, u = q.front(); if(u.a==s/2&&u.s==s/2){ return u.t; } if(u.s&&u.a!=a){ int c = a - u.a; if(u.s>=c){ v.a = a; v.s = u.s - c; } else{ v.a = u.a + u.s; v.s = 0; } v.b = u.b; v.t = u.t + 1; if(!vis[v.a][v.b]){ vis[v.a][v.b] = 1; q.push(v); } } if(u.s&&u.b!=b){ int c = b - u.b; if(u.s>=c){ v.b = b; v.s = u.s - c; } else{ v.b = u.b + u.s; v.s = 0; } v.a = u.a; v.t = u.t + 1; if(!vis[v.a][v.b]){ vis[v.a][v.b] = 1; q.push(v); } } if(u.a&&u.b!=b){ int c = b - u.b; if(u.a>=c){ v.b = b; v.a = u.a - c; } else{ v.b = u.b + u.a; v.a= 0; } v.s = u.s; v.t = u.t + 1; if(!vis[v.a][v.b]){ vis[v.a][v.b] = 1; q.push(v); } } if(u.a&&u.s!=s){ int c = s - u.s; if(u.a>=c){ v.s = s; v.a = u.a - c; } else{ v.s = u.s + u.a; v.a= 0; } v.b = u.b; v.t = u.t + 1; if(!vis[v.a][v.b]){ vis[v.a][v.b] = 1; q.push(v); } } if(u.b&&u.a!=a){ int c = a - u.a; if(u.b>=c){ v.a = a; v.b = u.b - c; } else{ v.a = u.a + u.b; v.b= 0; } v.s = u.s; v.t = u.t + 1; if(!vis[v.a][v.b]){ vis[v.a][v.b] = 1; q.push(v); } } if(u.b&&u.s!=s){ int c = s - u.s; if(u.b>=c){ v.s = s; v.b = u.b - c; } else{ v.s = u.s + u.b; v.b= 0; } v.a = u.a; v.t = u.t + 1; if(!vis[v.a][v.b]){ vis[v.a][v.b] = 1; q.push(v); } } q.pop(); } return 0; } int main(){ while ((cin>>s>>a>>b)&&(a||b||s)) { if(s%2==1){ cout << "NO" << endl; } else{ if(a<b){ swap(a, b); } int ans = bfs(); if(ans){ cout << ans << endl; } else{ cout << "NO" << endl; } } } return 0; }