邮票面值设计
描述
给定一个信封,最多只允许粘贴N张邮票,计算在给定M(N+M<=10)种邮票的情况下(假定所有的邮票数量都足够),如何设计邮票的面值,能得到最大max ,使得1~max之间的每一个邮资值都能得到。
例如,N=3,M=2,如果面值分别为1分、4分,则在l分~6分之间的每一个邮资值都能得到(当然还有8分、9分和12分):如果面值分别为1分、3分,则在1分~7分之间的每一个邮资值都能得到。可以验证当N=3,M=2时,7分就是可以得到连续的邮资最大值,所以MAX=7,面值分别为l分、3分。
样例输入:共一行,两个整数,分表为N与M的值。
格式
输入格式
一行,分别为N,M。
输出格式
两行。
第一行为m种邮票的面值,按升序排列,各数之间用一个空格隔开。
第二行为最大值。
如果有多解,输出字典序最大的一个。
限制
各个测试点1s
来源
NOIP1999
70分超时三组
1 #include<iostream> 2 #include<cstdio> 3 #include<cstdlib> 4 #include<cstring> 5 #include<algorithm> 6 #include<cmath> 7 using namespace std; 8 int N,M; 9 int MAX; 10 int temp[50000];//存组合邮票 11 int T[50000]; 12 int vis[50000]; 13 int f[50000];//f[i]=K 表示邮票组成价值i要用 K张 14 void ser(int); 15 void DP(); 16 17 int main(){ 18 cin>>N>>M; 19 ser(1); 20 for(int i=1;i<=M;i++){ 21 cout<<T[i]<<" "; 22 } 23 cout<<endl; 24 cout<<"MAX="<<MAX; 25 return 0; 26 } 27 void ser(int now){ 28 if(now==M+1){ 29 DP(); 30 return ; 31 } 32 else{ 33 /* 34 for(int i=temp[now-1]+1;i<=(temp[now-1]*N+1);i++){ 35 temp[now]=i; 36 ser(now+1); 37 } 38 */ 39 for(int i=temp[now-1]*N+1;i>=temp[now-1]+1;i--){ 40 temp[now]=i; 41 ser(now+1); 42 } 43 } 44 } 45 void DP(){ 46 sort(temp+1,temp+M+1); 47 memset(f,0x3f3f3f3f,sizeof(f)); 48 f[0]=0; 49 50 for(int i=1;i<=200;i++){//i表示组成价值 51 for(int j=1;j<=M;j++){//使用第 j张邮票推过来 52 if(i-temp[j]>=0) 53 f[i]=min(f[i],f[i-temp[j]]+1); 54 else ; 55 } 56 if(f[i]<=N){ 57 if(i>MAX){ 58 MAX=i; 59 memcpy(T,temp,sizeof(temp)); 60 } 61 } 62 else return ; 63 } 64 }