hdu 1495 非常可乐


点击打开链接


题意:  给你三个杯子。 a,b,c.  且 a=b+c;


问你能不能将a里面的水平分。

能的话求出最少次数。

不能输出NO ;

很明显奇数是一定gg的。

直接暴力bfs来一发。每次可走的路可分为6条。 

a->b

a->c

b->a

......

就过了。

#include<bits/stdc++.h>
using namespace std;
const int maxn=101+10;
int vis[maxn][maxn][maxn];
int cup[5];
struct Cup{
    int gle[5],step;
}c;
int pour(int a,int b){
    int sum=c.gle[a]+c.gle[b];
    if(sum>=cup[b]) c.gle[b]=cup[b];
    else c.gle[b]=sum;
    c.gle[a]=sum-c.gle[b];
}
int bfs(){
    queue<Cup>que;
    Cup u,e;
    vis[cup[0]][0][0]=1;
    u.gle[0]=cup[0],u.gle[1]=0,u.gle[2]=0,u.step=0;
    que.push(u);
    while(!que.empty()){
        e=que.front();//printf("%d %d %d %d\n",e.gle[0],e.gle[1],e.gle[2],e.step);
        que.pop();
        if(e.gle[0]==e.gle[1]&&e.gle[2]==0) return e.step;
        for(int i=0;i<3;i++){
            for(int j=0;j<3;j++){
                if(i==j) continue;
                c=e;
                if(c.gle[i]==0) continue;
                pour(i,j);
                //for(int k=0;k<3;k++) if(c.gle[k]<0) continue;
                if(!vis[c.gle[0]][c.gle[1]][c.gle[2]]){
                    c.step++;
                    que.push(c);
                    vis[c.gle[0]][c.gle[1]][c.gle[2]]=1;
                }
            }
        }
    }
    return 0;
}
int main(){
    while(scanf("%d%d%d",&cup[0],&cup[1],&cup[2])&&(cup[0]+cup[1]+cup[2])){
        if(cup[0]&1) {
            printf("NO\n"); continue;
        }
        if(cup[1]<cup[2]) swap(cup[1],cup[2]);
        memset(vis,0,sizeof(vis));
        int ans=bfs();
        if(ans) printf("%d\n",ans);
        else printf("NO\n");
    }
    return 0;
}


另外还有数学规律:

设3个杯子a,b,c;

可以把问题转化成有两个杯子,通过这两个杯子加水倒水而达到水二分的目的。

可以设 b倒水x次

    c倒水y次

x,y为正时,表示到出,为负时表示倒入。

可列方程

bx+cy=(b+c)/2;

求|x|+|y| 最小值。 则对b,c取最小公倍数。

设g=gcd(b,c);

d=b/g;

e=c/g;

so::  dx+ey=(d+e)/2;

简单凑一下就可得出一组解。x=(1+d)/2;

 y=(1-e)/2;

显然x,y 一正一负。

|x|+|y|= |x-y|=(d+e)/2;

即为所求。减去本身状态,即为所求。

#include<bits/stdc++.h>
using namespace std;
const int maxn=101+10;
int gcd(int a,int b){
    return b==0?a:gcd(b,a%b);
}
int main(){
    int cup[5];
    while(scanf("%d%d%d",&cup[0],&cup[1],&cup[2])&&(cup[0]+cup[1]+cup[2])){
        int s=gcd(cup[1],cup[2]);
        cup[0]/=s;
        if(cup[0]&1) printf("NO\n");
        else printf("%d\n",cup[0]-1);
    }
    return 0;
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值