这题简直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;
}