题意:
某国家发行k种不同面值的邮票,而且规定每张信封上最多仅仅能贴h张邮票。
公式n(h,k)表示用从k中面值的邮票中选择h张邮票,能够组成面额为连续的1。2。3,……n。 n是能达到的最大面值之和。
快被坑死了。回溯法是能够的,能够利用回溯法推断能拼出的数值,可是利用动态规划的思想能够提高效率,dp[i]表示拼出i须要的最少数量邮票,tmp数组一開始定义成全局了,无限TLE,貌似由于出不了wa就超时了…………
代码:
#include<iostream> #include<cstring> #include<cstdio> #include<map> #include<cstring> #include<vector> #include<algorithm> #define INF 0X3f3f3f3f #define mem(a,b) memset(a,b,sizeof(a)) using namespace std; typedef long long ll; typedef unsigned long long llu; const int maxd=1000+50; int stamp[15] ,maxval[15],ans[15],dp[maxd]; int h,k; void solve(int cur) { if(cur==k) { if(maxval[k-1]>ans[k]) { memcpy(ans,stamp,sizeof(stamp)); ans[k]=maxval[k-1]; } return; } int tmp[maxd]; memcpy(tmp,dp,sizeof(dp)); for(int i=stamp[cur-1]+1; i<=maxval[cur-1]+1; ++i) { stamp[cur]=i; for(int j=1; j<=stamp[cur]*h; ++j) { for(int k=1; k<=h; ++k) { int num=k*stamp[cur]; if(j>=num && dp[j-num]>=0) { if(dp[j]<0 && dp[j-num]+k<=h) dp[j]=dp[j-num]+k; else if(dp[j-num]+k<dp[j]) dp[j]=dp[j-num]+k; } } int cnt=maxval[cur-1]; while(dp[cnt]>0) ++cnt; maxval[cur]=cnt-1; } solve(cur+1); memcpy(dp,tmp,sizeof(tmp)); } } int main() { freopen("1.txt","r",stdin); while(scanf("%d%d",&h,&k)==2 && (h+k)) { ans[k]=0; stamp[0]=1,maxval[0]=h; mem(dp,-1); for(int i=0; i<=h; ++i) dp[i]=i; solve(1); for(int i=0; i<k; ++i) printf("%3d",ans[i]); printf(" ->%3d ",ans[k]); } return 0; }