uva--165(邮资问题,dp)

来源:互联网 发布:怎样注册2个淘宝账号 编辑:程序博客网 时间:2024/06/07 03:22

题意:

某国家发行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;}


0 0
原创粉丝点击