1. 程式人生 > 實用技巧 >HDU1495 非常可樂(兩種解法)

HDU1495 非常可樂(兩種解法)

題目連結: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;
}