165(邮资问题,dp)

题意:

某国家发行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\n",ans[k]);}return 0;}

世上没有绝望的处境,只有对处境绝望的人。

165(邮资问题,dp)

相关文章:

你感兴趣的文章:

标签云: