HDU 1495 非常可乐

- HDU 1495 -

非常可乐

Problem 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"。

Author

seeyou

解题思路:

宽度优先搜素 or 数论
感觉和 POJ 上的这题差不多,都是关于操作步骤的,用 bfs 就可以了–>- POJ 3414 Pots(bfs)-
不过后来看到 discuss 里面居然有人直接用 gcd 就过了,然后又看到一种貌似更复杂的?提到数论裴蜀定理,这,,,见多识广真好~o( ̄︶ ̄)o

代码:

① bfs:
Exe.Time : 15MS | Exe.Memory : 1796K

#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <algorithm>
#include <cmath>
#include <stack>
#include <queue>
#include <vector>
#include <map>
using namespace std;
#define INF 0x3f3f3f
#define zero 1e-7

typedef long long ll;
const int N=110;
int vis[N][N];//i|j分别表示两个杯子中的水量,vis记录到达这种状态最少需要的步骤
int s, n, m;

struct node {
    int v1, v2, v3;
};
queue<node> q;

int bfs(int vs, int vn, int vm) {
    while(!q.empty()) q.pop();
    node st={vs, vn, vm};
    q.push(st);
    vis[vn][vm]=0;
    while(!q.empty()) {
        node top=q.front();
        //printf("top.v1=%d, v2=%d, v3=%d\n", top.v1, top.v2, top.v3);
        q.pop();
        if((top.v1==top.v2 && !top.v3) || (top.v1==top.v3 && !top.v2) || (top.v2==top.v3 && !top.v1))
            return vis[top.v2][top.v3];
        int a=top.v1, b=top.v2, c=top.v3;
        for(int i=0; i<6; i++) {
            switch(i) {
                case 0: //s-->n(之前不小心把数字打成字符了,所以实际上并没有进行任何操作
                    if(top.v1+top.v2>=n)
                        b=n, a=top.v1+top.v2-n;
                    else
                        a=0, b=top.v1+top.v2;
                    c=top.v3;
                    break;
                case 1://s-->m
                    if(top.v1+top.v3>=m)
                        c=m, a=top.v1+top.v3-m;
                    else
                        a=0, c=top.v1+top.v3;
                    b=top.v2;
                    break;
                case 2://n-->s
                    a=top.v1+top.v2;
                    b=0;
                    c=top.v3;
                    break;
                case 3://n-->m
                    if(top.v2+top.v3>=m)
                        c=m, b=top.v2+top.v3-m;
                    else
                        b=0, c=top.v2+top.v3;
                    a=top.v1;
                    break;
                case 4://m-->s
                    a=top.v1+top.v3;
                    c=0;
                    b=top.v2;
                    break;
                case 5://m-->n
                    if(top.v2+top.v3>=n)
                        b=n, c=top.v2+top.v3-n;
                    else
                        c=0, b=top.v2+top.v3;
                    a=top.v1;
                    break;
            }
            //printf("vis[%d][%d]=%d\n", b, c, vis[b][c]);
            if(vis[b][c]==-1) {
                vis[b][c]=vis[top.v2][top.v3]+1;
                node temp={a, b, c};
                q.push(temp);
            }
        }
    }
    return -1;
}

int main() {
    while(scanf("%d %d %d", &s, &n, &m)!=EOF, s || n || m) {
        if(s%2) printf("NO\n");
        else {
            memset(vis, -1, sizeof(vis));
            int ans=bfs(s, 0, 0);
            if(ans!=-1) printf("%d\n", ans);
            else printf("NO\n");
        }
    }
    return 0;
}
//ps: 过了就非常可乐(#^.^#)

② gcd:
Exe.Time : 46MS | Exe.Memory : 1804K

#include <iostream>
#include <algorithm>

using namespace std;

int gcd(int a, int b)  {
  return a%b ? gcd(b, a%b) : b;
}

void print(int a) {
  if(a & 1) cout << "NO\n";
  else cout << a-1 << endl;
}

int main()
{
  int a, b, c;
  while((cin>>a>>b>>c) && (a||b||c)) {
    a /= gcd(b, c);
    print(a);
  }
}

③ 数论:
Exe.Time : 31MS | Exe.Memory : 1740K
链接:- 冲啊小笼包 -

PS: 事实证明,还是 bfs 跑得快一点,就是代码有点长~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值