Holding Bin-Laden Captive!
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 13861 Accepted Submission(s): 6230
Problem Description
We all know that Bin-Laden is a notorious terrorist, and he has disappeared for a long time. But recently, it is reported that he hides in Hang Zhou of China!
“Oh, God! How terrible! ”
Don’t be so afraid, guys. Although he hides in a cave of Hang Zhou, he dares not to go out. Laden is so bored recent years that he fling himself into some math problems, and he said that if anyone can solve his problem, he will give himself up!
Ha-ha! Obviously, Laden is too proud of his intelligence! But, what is his problem?
“Given some Chinese Coins (硬币) (three kinds– 1, 2, 5), and their number is num_1, num_2 and num_5 respectively, please output the minimum value that you cannot pay with given coins.”
You, super ACMer, should solve the problem easily, and don’t forget to take $25000000 from Bush!
Input
Output
Output the minimum positive value that one cannot pay with given coins, one line for one case.
Sample Input
1 1 3
0 0 0
Sample Output
4
题意:给定三中硬币,面值分别为1,2,5,并且给定三种硬币的数量分别为num_1,num_2,num_5,然后让求解这些硬币所不能组成的最小的面额是多少,例如给定的例子,面值为1的硬币为1枚,面值为2的硬币为1枚,面值为5的硬币为3枚,则可以组成的面值有1,2,3,5……所以,不能组成的最小面额为4。这就是一道母函数的问题,但是这里并不是求组合数,所以,不需要int行的数组来记录组合数,只需要true和false来标示是否能表示该面值就可以了。当然用int记录组合数也可以,但要注意,因为组合量非常大,要注意溢出的情况,我试了一下可以,判断大于0的时候置1就能过。
代码:
# include <iostream>
# include <cstring>
using namespace std;
int main(){
int n,i,j,k,m;
int money[9];//金钱的面值
int c1[10000],c2[10000];
while(cin>>money[1]>>money[2]>>money[5]&&money[1]||money[2]||money[5]){
//利用下标
memset(c1,0,sizeof(c1));
memset(c2,0,sizeof(c2));
m = money[1]*1+money[2]*2+money[5]*5;//计算出面值的最大值
for(i=0;i<=money[1];i++){//初始化第一项
c1[i] = 1;
}
for(i=2;i<=5;i+=3){//代表第二项与第三项
for(j=0;j<=m;j++){// m代表最大的面值,
for(k=0;k+j<=m&&k/i<=money[i];k+=i){ //面值k=i*money[i]; k代表2或5面值的和
c2[k+j]+= c1[j];
}
}
for(k=0;k<=m;k++){
c1[k] = c2[k];
c2[k] = 0;
}
}
for(i=1;i<=m;i++){
if(!c1[i]){
break;
}
}
cout<<i<<endl;
}
}
方法2:
# include <iostream>
using namespace std;
int main()
{
int a,b,c;
while(cin>>a>>b>>c)
{
if(a==0&&b==0&c==0)
break;
if(a==0)
printf("1\n");
else if(a+2*b<4)//a>=1,b只能是0
printf("%d\n",a+2*b+1);
else//a!=0&&b1!=0 c不确定
printf("%d\n",a+2*b+5*c+1);
}
return 0;
}
代码3:
# include <iostream>
# include <cstring>
using namespace std;
# define MAX 10000
int c1[MAX],c2[MAX];
int num[4];
int main(){
while(cin>>num[1]>>num[2]>>num[3]&&num[1]||num[2]||num[3]){
int max_ = num[1]*1 + num[2]*2 + num[3]*5;
int i,j,k;
memset(c1,0,sizeof(c1));
memset(c2,0,sizeof(c2));
for(i=0;i<=num[1];i++){//对第一项初始化
c1[i] = 1;
}
//这两层for的作用就是第一项的每一个数与第二项的每一数相乘
for(i=0;i<=num[1];i++){//代表第一项
for(j=0;j<=num[2]*2;j+=2){//代表第二项
c2[i+j] += c1[i];// c2[i+j]-->代表取系数 c1[i]-->代表取ax^n中的a,即系数
}
}
/*
for循环中间的条件为什么是 j<=num[1]*1+num[2]*2
上面是第一项与第二项的for循环是 x^a与x^b相加==x^(a+b) 最大值是num[1]*1+num[2]*2
*/
for(j=0;j<=num[1]*1+num[2]*2;j++){
c1[j] = c2[j];
c2[j] = 0;
}
for(i=0;i<=num[1]*1+num[2]*2;i++){
for(j=0;j<=num[3]*5;j+=5){
c2[j+i] += c1[i];
}
}
for(j=0;j<=num[1]*1+num[2]*2+num[3]*5;j++){
c1[j] = c2[j];
c2[j] = 0;
}
for(j=0;j<=max_;j++){
if(c1[j]==0){
break;
}
}
cout<<j<<endl;
}
return 0;
}
Runtime Error(ACCESS_VIOLATION)数组开的太小