P1021 邮票面值设计(dfs+背包dp)

P1021 邮票面值设计

题目传送门

题意:

给定一个信封,最多只允许粘贴N张邮票,计算在给定KN+K≤15N+K15)种邮票的情况下

(假定所有的邮票数量都足够),如何设计邮票的面值,能得到最大值MAX

使在1至MAX之间的每一个邮资值都能得到。

思路:

dfs+背包dp

  暴搜k种邮票,下一种邮票的取值就是上一张邮票值+1,到上一次选的最大值+1;

   比如这上一次你选了1,n=3时,下一次你能选的就是2,3,4;

  然后怎么确定当前选择i之后的最大值呢,就是用到背包dp,dp[i]表示凑

  到i时所用的最少邮票数。

代码:

#include<bits/stdc++.h>
using namespace std;
#define N 105
int n,k;
int res;
int ans[N],tmp[N],dp[2005];

int get(int cur,int sum)
{
    memset(dp,0x3f3f3f3f,sizeof(dp));
    dp[0]=0;
    for(int i=1;i<=cur;i++)
    {
        for(int j=tmp[i];j<=n*sum;j++)
            dp[j]=min(dp[j],dp[j-tmp[i]]+1);;
    }
    for(int i=1;i<=n*sum;i++)
        if(dp[i]>n) return i-1;
    return n*sum;
}
void dfs(int cur,int L1,int L2,int sum)
{
    if(cur>k)
    {
        if(res<L2)
        {
            res=L2;
            for(int i=1;i<=n;i++)
                ans[i]=tmp[i];
        }
        return ;
    }
    for(int i=L1+1;i<=L2+1;i++)
    {
        tmp[cur]=i;
        int x=get(cur,sum+i);
        dfs(cur+1,i,x,sum+i);
    }
}
int main()
{
    while(~scanf("%d %d",&n,&k))
    {
        res=0;
        dfs(1,0,0,0);
        for(int i=1;i<=k;i++)
            printf("%d ",ans[i]);
        printf("
MAX=");
        printf("%d
",res);
    }
    return 0;
}
View Code
原文地址:https://www.cnblogs.com/zhgyki/p/10372178.html