hdoj 1085 Holding Bin-Laden Captive!

Holding Bin-Laden Captive!

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 17696    Accepted Submission(s): 7918


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
Input contains multiple test cases. Each test case contains 3 positive integers num_1, num_2 and num_5 (0<=num_i<=1000). A test case containing 0 0 0 terminates the input and this test case is not to be processed.
 

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+x +x^2+x^3+.........x^num1) *( 1+x^2+x^4+x^6+.........x^num2) *( 1+x^5+x^10+x^15+............x^num5)

其中num1代表一分的硬币有多少个,num2代表2分的硬币多少个,num5代表5分的硬币有多少个。

模拟三个式子相乘,先前两个,合并后和第三个相乘。一定要注意指数的变化范围。给定了num1 num2 num5后,每一个式子的最大指数和计算后的总式子的最大指数都是确定的。

代码:
#include<stdio.h>
#include<iostream>
#include<string.h>
using namespace std;
int num1,num2,num5;
int c1[100000],c2[100000]; //注意范围,计算方法为 1000*1+1000*2+1000*5 ,8000为最大指数
int main()
{
	int n,m,k,i,j;
	while(scanf("%d%d%d",&num1,&num2,&num5)!=EOF&&(num1||num2||num5))
	{
		int max;
		max=1*num1+2*num2+5*num5;//最大的指数
		memset(c1,0,sizeof(c1));
		memset(c2,0,sizeof(c2));
		for(i=0;i<=num1;i++)
		 {
		 	c1[i]=1;
		 }
		 for(i=0;i<=num1;i++)//先模拟前两个式子相乘
		 {
		 	for(j=0;j<=2*num2;j+=2)//因为没有给定要求的最大指数,所以不用 j+i<= 多少
		 	{
		 		c2[j+i]+=c1[i];
			 }
		 }
		 for(i=0;i<=num1+2*num2;i++)//模拟前两个式子合并后的式子与第三个式子相乘,num1+2*num2是前两个式子相乘后的最大指数
		 {
		 	c1[i]=c2[i];
		 	c2[i]=0;
		 }
		 for(i=0;i<=num1+2*num2;i++)
		  {
		  	for(j=0;j<=5*num5;j+=5)
		  	{
		  		c2[j+i]+=c1[i];
			  }
		  }
		  for(i=0;i<=max;i++)
		   {
		   	c1[i]=c2[i];
		   	c2[i]=0;
		   }
		   for(i=0;i<=max;i++)
		   {
		   	if(c1[i]==0)//系数为0说明,该指数不存在
		   	{
			   printf("%d\n",i);
		   	break;
		     }
		   }
		   if(i==max+1)//如果前面的都 满足则max+1项即为答案! 
		   printf("%d\n",i);
		   
	}
	return 0;
} 

当然也可以放在循环里面:
代码:
#include<stdio.h>
#include<string.h>
#include<iostream>
using namespace std;
#define N 10000
int c1[N],c2[N];
int num[4],money[4];
int main()
{
	int i,j,k;
	while(scanf("%d%d%d",&num[1],&num[2],&num[3])!=EOF&&(num[1]||num[2]||num[3]))
	{
		int max;
		memset(c1,0,sizeof(c1));
		memset(c2,0,sizeof(c2));
		for(i=0;i<=num[1];i++)//把第一组数(第一括号)的数 至一 
		 {
		 	c1[i]=1;
		 }
		 max=0;
		 int maxx=0;
		 money[2]=2;money[3]=5,money[1]=1;
		 for(i=1;i<=3;i++)
		  {
		  	maxx+=money[i]*num[i];
		  }
		 for(i=1;i<3;i++)
		  {
		  	max+=num[i]*money[i];// 和上面一个原理 
		  	for(j=0;j<=max;j++)
		  	 {
		  	 	for(k=0;k<=money[i+1]*num[i+1];k+=money[i+1])
		  	 	{
		  	 		c2[j+k]=c1[j];
				}
			 }
			 memcpy(c1,c2,sizeof(c2));
		  memset(c2,0,sizeof(c2));
		  }
		  for(i=0;i<=maxx;i++)
		  {
		  	if(c1[i]==0)
		  	{
		  		printf("%d\n",i);
		  		break;
			  }
			  
		  }
		  if(maxx+1==i)
		  printf("%d\n",i);
		  
	} 
	return 0;
}

当然,此题用母函数并不是最好解法。最好解法如下,

稍加分析可知,面值大的不能表示面值小的,所以我们要先考虑面值小的硬币。

如果1-4分可以全部被表示,那么它可以表示当前硬币的所有组合。那么结果就应该是所有硬币价值总和加一。

如果1-4分不可以全部被表示,那么它所不能表示的最小价值就应该是这1-4分中不可以被表示的最小价值。

代码如下。

#include<stdio.h>
int main()
{
	int n,m,k;
	while(scanf("%d%d%d",&n,&m,&k)!=EOF&&(n||m||k))
	{
		if(n==0)
		{
		printf("-1\n"); 
		continue; 
		} 
		else if(n+2*m<4)
		printf("%d\n",n+2*m+1);
		else 
		printf("%d\n",n+2*m+5*k);
	}
	return 0;
 } 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值