邮票面值设计
Posted lcan
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了邮票面值设计相关的知识,希望对你有一定的参考价值。
给定一个信封,最多只允许粘贴N张邮票,计算在给定K(N+K≤15)种邮票的情况下(假定所有的邮票数量都足够),如何设计邮票的面值,能得到最大值MAX,使在1至MAX之间的每一个邮资值都能得到。
例如,N=3,K=2,如果面值分别为1分、4分,则在1分~6分之间的每一个邮资值都能得到(当然还有8分、9分和12分);如果面值分别为1分、3分,则在1分~7分之间的每一个邮资值都能得到。可以验证当N=3,K=2时,
7分就是可以得到的连续的邮资最大值,所以MAX=7,面值分别为1分、3分。
输入输出格式
输入格式:
2个整数,代表N,K。
输出格式:
2行。第一行若干个数字,表示选择的面值,从小到大排序。
第二行,输出“MAX=S”,S表示最大的面值。
这是用搜索来解决选什么面值,用DP来解决是否能凑出要求的值来
搜索的上下边界没有想到 a[x]:a[x-1]+1,a[x-1]*n+1
因为搜索的顺序是从小到大,所以a[x-1]+1,又因为要求数要连续,所以如果n张都贴当前最大值的后一个一定要凑出来
然后也不知道要怎么求出最大的能连续凑出的值来
dp[i]表示凑出i这种面值所需要的最小的张数,如果>n,i-1就是最大的能被连续凑出的面值
i要从小到大推进,j枚举就可以了 从1到k
1 #include<iostream> 2 #include<cstdio> 3 using namespace std; 4 const int maxn=1e4+7; 5 const int INF=0x7f7f7f7f; 6 int n,k,ans; 7 int a[maxn],imax[maxn],dp[maxn]; 8 void pan(){ 9 int i=0;dp[0]=0; 10 while(dp[i]<=n){ 11 dp[++i]=INF; 12 for(int j=1;j<=k;j++){ 13 if(i<a[j]) continue; 14 dp[i]=min(dp[i],dp[i-a[j]]+1); 15 } 16 } 17 if(i-1>ans){ 18 ans=i-1; 19 for(int j=1;j<=k;j++) {imax[j]=a[j];} 20 } 21 } 22 void dfs(int x){ 23 if(x==k+1){ 24 pan(); 25 return; 26 } 27 for(int i=a[x-1]+1;i<=a[x-1]*n+1;i++){ 28 a[x]=i;dfs(x+1); 29 } 30 } 31 int main(){ 32 cin>>n>>k;dfs(1); 33 for(int i=1;i<=k;i++) cout<<imax[i]<<" "; cout<<endl; 34 cout<<"MAX="<<ans<<endl; 35 return 0; 36 }
以上是关于邮票面值设计的主要内容,如果未能解决你的问题,请参考以下文章