非常可乐

题目链接:hdu 1495

题目大意

  • 一瓶可乐容量是S,只有两个没有刻度的杯子,容量分别是a和b,可乐杯子之间可以相互倒
  • 由于没有刻度,那么就肯定是要么倒完,要么倒满
  • 问是否能平分这一瓶可乐,如果可以输出最少倒的次数,否则输出"NO"

思路

  • bfs
  • 用广搜模拟六种情况,就是s->a,s->b,a->s,a->b,b->s,b->a这六种情况,s->a表示拿s往a中倒可乐,然后记录步数
  • 当三个容器中出现两个容量是s/2,另外一个是0的情况,说明可以平分,输出步数
  • set记录状态,如果出现过了,就不再进队列,如果出队列还没返回值,直接返回-1
  • 如果返回-1,则输出"NO"

ac代码

#include<bits/stdc++.h>
using namespace std;
#define ll long long
struct node{
    int s, a, b, dep;
};
int s, a, b;
bool ok(node a){
    vector<int> v;
    int ss = 0;
    v.push_back(a.s);
    v.push_back(a.a);
    v.push_back(a.b);
    sort(v.begin(), v.end()); //排序方便看最大最小值
    return v[0] == 0 && v[1] == s / 2 && v[2] == s / 2;
}
int bfs(){
    set<string> ss;
    queue<node> q;
    q.push({s, 0, 0, 0}); //初始状态
    while(q.size()){
        node t = q.front(); q.pop();
        string aa = to_string(t.s) + "-" + to_string(t.a) + "-" + to_string(t.b); //把状态转换成字符串
        if(ss.count(aa)) continue; //set记录状态
        ss.insert(aa);
        if(ok(t)) {
            return t.dep; //返回步数
        }
        node tmp;
        //s -> a
        tmp = t; tmp.dep ++; 
        tmp.a += tmp.s; tmp.s = 0; //先全部倒完
        if(tmp.a >= a) tmp.s += tmp.a - a, tmp.a = a;//多余部分还给s容器
        q.push(tmp); //下同
        //s -> b
        tmp = t; tmp.dep ++;
        tmp.b += tmp.s; tmp.s = 0;
        if(tmp.b >= b) tmp.s += tmp.b - b, tmp.b = b;
        q.push(tmp);
        //a -> s
        tmp = t; tmp.dep ++;
        tmp.s += tmp.a; tmp.a = 0; //s不会超,所以没必要判断是否会多余
        q.push(tmp);
        //a -> b
        tmp = t; tmp.dep ++;
        tmp.b += tmp.a; tmp.a = 0;
        if(tmp.b >= b) tmp.a += tmp.b - b, tmp.b = b;
        q.push(tmp);
        //b -> s
        tmp = t; tmp.dep ++;
        tmp.s += tmp.b; tmp.b = 0;
        q.push(tmp);
        //b -> a
        tmp = t; tmp.dep ++;
        tmp.a += tmp.b; tmp.b = 0;
        if(tmp.a >= a) tmp.b += tmp.a - a, tmp.a = a;
        q.push(tmp);
    }
    return -1; //如果还不行则返回-1
}
int main(){
    while(~scanf("%d%d%d", &s, &a, &b)){
        if(s + a + b == 0) break;
        int ans = bfs();
        if(ans == -1) puts("NO");
        else printf("%d\n", ans);
    }
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值