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

时间:2022-05-22 08:39:44

P1021 邮票面值设计

题目传送门

题意:

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

(假定所有的邮票数量都足够),如何设计邮票的面值,能得到最大值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[]; int get(int cur,int sum)
{
memset(dp,0x3f3f3f3f,sizeof(dp));
dp[]=;
for(int i=;i<=cur;i++)
{
for(int j=tmp[i];j<=n*sum;j++)
dp[j]=min(dp[j],dp[j-tmp[i]]+);;
}
for(int i=;i<=n*sum;i++)
if(dp[i]>n) return i-;
return n*sum;
}
void dfs(int cur,int L1,int L2,int sum)
{
if(cur>k)
{
if(res<L2)
{
res=L2;
for(int i=;i<=n;i++)
ans[i]=tmp[i];
}
return ;
}
for(int i=L1+;i<=L2+;i++)
{
tmp[cur]=i;
int x=get(cur,sum+i);
dfs(cur+,i,x,sum+i);
}
}
int main()
{
while(~scanf("%d %d",&n,&k))
{
res=;
dfs(,,,);
for(int i=;i<=k;i++)
printf("%d ",ans[i]);
printf("\nMAX=");
printf("%d\n",res);
}
return ;
}