春天的打水梦

这题简直nice!!! 

问题 : 春天的打水梦

时间限制: 1 Sec  内存限制: 128 MB
提交: 97  解决: 7
[提交] [状态] [讨论版] [命题人:admin]

题目描述

现有一个池塘里面有无数升的水,师傅让春天去打水并给了春天两个空水壶,容积分别为e升和f升,又给了容量为g升的桶,问春天最少多少次能将桶打满。(只能用空水壶打水,且没有其他度量工具,每次打满一壶水算做打水一次,且桶只能进水不能出水)

输入

每行三个整数e,f,g;分别为两个空水壶,以及空桶的容量。(0<e,f,g<1e7)

输出

是否能将桶打满,
如果能就输出Yes,并输出最少打水的次数两者用空格隔开。反之输出No。

样例输入

5 6 8
4 6 7

样例输出

Yes 3
No

 刚开始没有看懂测试数据为什么这样,看了解释之后恍然大悟,果然小编还需提高智商啊QAQ~

有两个壶分别为a,b升,(使a>b)以及一个桶c升。

打水一次有三个模式,分别为用a壶打一次,用b壶打一次,用a-b打一次(即a打水倒入b所剩余a-b),

1.这三种模式,是无限次的 ,我们就可以当做完全背包来理解。

2.可得等式ax+by=c或者ax+(a-b)y=c满足这两个等式才有解。 典型的扩展欧几里得。

题目就转化为求上面两个方程式的x+y的最小解,不过注意x>=0&&y>=0。

3.1e7直接暴力解决不超时

#include<cstdio>
#include<cstring>
#include<math.h>

#define INF 0x3f3f3f3f
#define LL long long
#define N 10000009

int dp[N];
int main()
{
    int e,f,g;
    while(scanf("%d%d%d",&e,&f,&g)!=EOF)
    {
        for(int i=1;i<=g;i++) dp[i]=INF;

        dp[0]=0;
        for(int i=e;i<=g;i++)
            dp[i]=min(dp[i],dp[i-e]+1);
        for(int i=f;i<=g;i++)
            dp[i]=min(dp[i],dp[i-f]+1);
        if(e!=f)
        {
            for(int i=abs(e-f);i<=g;i++)
                dp[i]=min(dp[i],dp[i-abs(e-f)]+1);
        }
        if(dp[g]>=INF)
        {
            printf("No\n");
            continue;
        }
        printf("Yes %d\n",dp[g]);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_40564464/article/details/81866081