问题描述
给定一个信封,最多只允许粘贴N张邮票,计算在给定K(N+K≤40)种邮票的情况下(假定所有的邮票数量都足够),如何设计邮票的面值,能得到最大值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分。
样例:
INPUT
3 2
OUTPUT
1 3
MAX=7
思路:深搜加上dp。每次深搜中j的取值范围从上一次+1到上一次能取到的最大值+1,能减少循环次数。对于最大值的取得情况用dp,类似于背包。
#include<iostream> #include<cstring> using namespace std; int n,k,a[41]={0},ansd[41]={0},ans=0,piece[30001]={0}; int rmb(int i) { int j,t,maxx; memset(piece,0,sizeof(piece)); for (j=1;j<=i;++j) piece[a[j]]=1; maxx=1; do { ++maxx; for (j=1;j<=i;++j) if (maxx-a[j]>=0) { if (piece[maxx]==0) piece[maxx]=piece[maxx-a[j]]+1; if (piece[maxx]>piece[maxx-a[j]]+1) piece[maxx]=piece[maxx-a[j]]+1; } if ((piece[maxx]==0)||(piece[maxx]>n)) return maxx-1; } while (true); } void dfs(int i,int maxn) { int j; if (i==k+1) { if (maxn>ans) { ans=maxn; for (j=2;j<=k;++j) ansd[j]=a[j]; } return; } for (j=a[i-1]+1;j<=maxn+1;++j) { a[i]=j; maxn=rmb(i); dfs(i+1,maxn); } } int main() { int i; cin>>n>>k; a[1]=1; ansd[1]=1; dfs(2,n); for (i=1;i<=k;++i) cout<<ansd[i]<<" "; cout<<endl<<"MAX="<<ans<<endl; }
RZUC Code
时间: 2024-11-06 19:05:58