JD 1147:Jugs(一种用最少步骤求解的方法)

本文介绍了解决水壶问题的一种高效方法,通过分析不定方程,利用试探法找出满足条件的解,从而实现目标水量。详细步骤包括计算解的范围、选择合适的填充和倒水策略,以及提供具体实例来验证方法的有效性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

OJ题目:click here~~

题目分析:九度上这道没有要求最少步数,只要得到最后结果即可AC , bfs , dfs都行。最少步骤的方法肯定也能AC啦,分析如下。

输入的三个数:a,b,n;
> 由题不定方程ax+by=n必定有解
> 如果b=n,则fill B即可,否则用试探法求出这样的两组解(a1,b1)及(a2,b2),其中a1 >0,b1<0;a1是满足方程的最小正整数;a2<0,b2>0,a2是满足条件的最大负整数;
> (i)  如果|a1|+|b1|<|a2|+|b2|-1,则fill A a1次,每次fill A后,pour到B,如果B满则empty B,再将A中剩下的pour到B,这样empty B |b1|次以后,即可得解;(因为a*a1+b*b1=n)
> (ii)如果|a1|+|b1|>=|a2|+|b2|-1,则fill B b2次,每次fill B后,pour到A,如果A满则empty A,再将B中剩下的pour到A,这样经过empty A |a2|-1次以后,再将A装滿,B中剩下的就是n了;
> 
> Sample Input
> 
> 3 5 4 
> 5 7 3 
> 3x+5y=4的两组解为(2,-1),(-2,2)
> 2+1=1+2;
> 用方法II:(fill B两次,empty A 一次)
> fill B (第一次fill B)
> pour B A 
> empty A (A 滿清空A)(这里只需要清一次A,因为a2=-1)
> pour B A (B中剩下的到A)
> fill B (第二次fill B)
> pour B A (装滿 A,B中剩下的即为n)
> success 
> 
> 5x+7y=3的两组解为(2,-1)(-5,4)
> 2+1<5+4
> 用方法I:(fill A 两次empty B 一次)
> fill A (第一次fill A)
> pour A B 
> fill A (第二次fill A)
> pour A B 
> empty B 
> pour A B 
> success 

int main(){
    //freopen("in.txt","r",stdin) ;
    int i , j , n , A , B ;
    while(cin >> A >> B >> n){
        int a1 , b1 , a2 , b2 , a , b , t ;
        int x , y ;
        for(i = 1; ;i++){
            y = n - A*i ;
            if(y%B == 0 && y < 0){
                a1 = i ;
                b1 = y/B ;
                break ;
            }
        }
        for(i = -1; ;i--){
            y = n - A*i ;
            if(y%B == 0 && y > 0){
                a2 = i ;
                b2 = y/B ;
                break ;
            }
        }
        a = b = 0 ;
        if(abs(a1) + abs(b1) < abs(a2) + abs(b2) - 1){
            t = abs(b1) ;
            for(i = 0;i < a1;i++){
                puts("fill A") ;
                a = A ;
                puts("pour A B") ;
                if(!t) break ;
                if(a + b >= B){
                    puts("empty B") ;
                    puts("pour A B") ;
                    t-- ;
                    a = a + b - B ;
                    b = 0 ;
                    b = a ;
                    a = 0 ;
                }
                else{
                    b = a + b ;
                    a = 0 ;
                }
            }
        }
        else{
            t = abs(a2) - 1 ;
            for(i = 0;i < b2;i++){
                puts("fill B") ;
                b = B ;
                puts("pour B A") ;
                if(!t) break ;
                if(a + b >= A){
                    puts("empty A") ;
                    puts("pour B A") ;
                    t-- ;
                    b = a + b - A ;
                    a = 0 ;
                    a = b ;
                    b = 0 ;
                }
                else{
                    a = a + b ;
                    b = 0 ;
                }
            }
        }
        puts("success") ;
    }
    return 0 ;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值