[NOIP1999]邮票面值设计

题目描述

  给定一个信封,最多只允许粘贴N张邮票,计算在给定K种邮票的情况下(假定所有的邮票数量都足够),如何设计邮票的面值,能得到最大max,使得1-max之间的每一个邮资值都能得到。
  例如,N=3,K=2,如果面值分别为1分、4分,则在l分-6分之间的每一个邮资值都能得到(当然还有8分、9分和12分):如果面值分别为1分、3分,则在1分-7分之间的每一个邮资值都能得到。可以验证当N=3,K=2时,7分就是可以得到连续的邮资最大值,所以max=7,面值分别为l分、3分。
[数据范围]
100%的数据,N + K <= 10

输入格式

输入共一行。
第一行有两个数M、K由空格隔开。含义如前述。

输出格式

输出共两行。
第一行K个数由空格隔开,表示邮票设计方案,要求面值大小升序输出。
第二行输出最大面值max。

通过这道题我对搜索有了更新的认识——要不惜一切代价剪枝!

一开始的做法是随便设置一个搜索范围,只有40分,看了题解后才发现需要用动态规划剪枝,强!

不惜一切代价剪枝!

 1 #include<iostream>
 2 #include<string>
 3 using namespace std;
 4 
 5 int n,m,cord[11],ans[11],f[1000];
 6 
 7 int getbig(int deep){
 8     memset(f,0,sizeof(f));
 9      
10     for(int i=1;i<=1000;++i)
11     {
12       f[i]=1000;
13       for(int j=1;j<=deep;++j)
14       if(i>=cord[j]) f[i]=min(f[i],f[i-cord[j]]+1);      
15       if(f[i]>n) 
16       {
17         if(i>ans[0]) 
18         {ans[0]=i;for(int j=1;j<=deep;++j) ans[j]=cord[j];}
19         return i;          
20                  }
21             }
22      }
23 
24 void Dp(int deep){
25      int x=getbig(deep);
26      if(deep==m) return ;
27      
28      for(int i=x;i>cord[deep];--i)
29      {cord[deep+1]=i;Dp(deep+1);}
30      }
31 
32 int main()
33 {
34     cin>>n>>m;
35     cord[1]=1;
36     Dp(1);
37     
38     for(int i=1;i<=m;++i) cout<<ans[i]<<" ";cout<<endl;
39     cout<<"MAX="<<ans[0]-1<<endl;
40     //system("pause");                                
41     return 0; 
42     
43     } 
原文地址:https://www.cnblogs.com/noip/p/2686889.html