题目描述:
Baby Ming and Weight lifting
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 827 Accepted Submission(s): 318
Baby Ming prepare to use this two kinds of barbell disks to make up a new one weighted C (the barbell must be balanced), he want to know how to do it.
For each test case:
There are three positive integer a,b , and C .
1≤T≤1000,0<a,b,C≤1000,a≠b
Otherwise, print two numbers to indicating the numbers of a and b barbell disks are needed. (If there are more than one answer, print the answer with minimum a+b )
2 1 2 6 1 4 5
2 2 Impossible
题意:
有一个杠铃杆(重量忽略),和2种类型的杠铃片(重量分别为a和b),每种杠铃片都有无限个。
打算用这2种杠铃片组成重量为C的杠铃(杠铃必须平衡),他想让你告诉他,应该如何组合
输入一个正整数T(1≤T≤1000)表示测试组数
每组测试数据输入3个正整数a,b,C(0<a,b,C≤1000), 表示2种杠铃片的重量,以及杠铃的重量。
如果不能够组成重量为C的杠铃,输出Impossible。
否则输出2个数,表示需要a杠铃片的数量,和b杠铃片的数量。(如果有多种答案,输出a+b最小的方案)
解析:
这道题属于简单题,由于杠铃的杠铃片要成双,并且杠铃必须平衡,所以一开始我们的想法就是直接枚举即可
完整代码实现:
#include<cstdio>
#include<algorithm>
using namespace std;
int main()
{
int T;
int a,b,C;
while(scanf("%d",&T) == 1)
{
while(T--)
{
scanf("%d %d %d",&a,&b,&C);
if(C % 2 != 0)
printf("Impossible\n");
else
{
if(a < b)
{
bool tmp = false;
for(int i = 0; i <= 1000; i++)
{
for(int j = 0; j <= 1000; j++)
{
if(i*a+j*b == C/2)
{
printf("%d %d\n",2*i,2*j);
tmp = true;
break;
}
}
if(tmp) break;
}
if(!tmp) printf("Impossible\n");
}
else
{
bool tmp = false;
for(int i = 0; i <= 1000; i++)
{
for(int j = 0; j <= 1000; j++)
{
if(i*b+j*a == C/2)
{
printf("%d %d\n",2*j,2*i);
tmp = true;
break;
}
}
if(tmp) break;
}
if(!tmp) printf("Impossible\n");
}
}
}
}
return 0;
}
于是我们很快得到了这样的答案:
但是这样是否是我们满意的答案呢?明显不是的,在我们双重for循环暴力遍历的时候,很明显,存在很多不必要的遍历操作,如果不存在这样的a和b的组合的话,就要遍历1000*1000次,可想而知,效率是多么的底下,所以在内层和外层循环中,我们可以做一些判断,从而减少遍历的次数
内层循环中,是判断i,j两个值是否满足表达式,所以当遍历到i*a+j*b > c的情况时,由于是升序遍历,那么内层循环中后来的情况均不满足,因此可跳出内层循环。同样,在外层循环中也可设置类似条件,跳出循环从而减少遍历次数,提高程序效率。因此我们得出优化后的代码:
#include<cstdio>
#include<algorithm>
using namespace std;
int main()
{
int T;
int a,b,C;
scanf("%d",&T);
while(T--)
{
scanf("%d %d %d",&a,&b,&C);
if(C % 2 != 0)
printf("Impossible\n");
else
{
int c = C / 2;
bool tmp = false,flag = false;
if(a < b)
{
for(int i = 0; i <= 1000; i++)
{
if(tmp) break;
else if(i*a>c) break;
for(int j = 0; j <= 1000; j++)
{
if(i*a+j*b == c)
{
printf("%d %d\n",2*i,2*j);
tmp = true;
break;
}
else if(i*a+j*b > c) //类似于剪枝的思想,减少遍历次数
break;
}
}
if(!tmp) printf("Impossible\n");
}
else
{
for(int i = 0; i <= 1000; i++)
{
if(tmp) break;
else if(i*b>c) break;
for(int j = 0; j <= 1000; j++)
{
if(i*b+j*a == c)
{
printf("%d %d\n",2*j,2*i);
tmp = true;
break;
}
else if(i*b+j*a > c) //类似于剪枝的思想,减少遍历次数
break;
}
}
if(!tmp) printf("Impossible\n");
}
}
}
return 0;
}
很快,结果便出来了:
体会:在不改变可读性以及程序的正确性的情况下,自己应该有意识地优化自己的代码,这样的话才能使得自己的程序效率更高,而更加优雅。