邮票面值设计

 

描述

给定一个信封,最多只允许粘贴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种邮票的面值,按升序排列,各数之间用一个空格隔开。

第二行为最大值。

如果有多解,输出字典序最大的一个。

样例1

样例输入1[复制]

 
3 2

样例输出1[复制]

 
1 3
MAX=7

限制

各个测试点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 }

 

posted @ 2015-09-07 19:34  CXCXCXC  阅读(657)  评论(0编辑  收藏  举报