邮票面值设计java,[洛谷P1021][题解]邮票面值设计

本文详细介绍了使用深度优先搜索(DFS)和动态规划(DP)解决邮票组合问题的方法。首先通过DFS枚举所有可能的序列,然后利用DP计算出每个面值所需的最少邮票数量。在DP过程中,定义状态转移方程并进行优化,确保不重复计算。最终找到凑出指定面值所需的最小邮票组合。文章还提供了具体的代码实现,并对关键细节进行了注释,如上界设置和数组大小的确定。
摘要由CSDN通过智能技术生成

0.序

偶然被老师强迫刷到了这样一道题,正好亿年没写题解了,来此练练手+摸鱼。

1.概述

基本思路:DFS暴力枚举+DP验证。

先DFS出来一个序列,然后DP出所有面值用到的最少邮票数。

设\(f[i]\)为凑出\(i\)面值用到的最少邮票张数。

方程是我们在幼儿园就接触过的\(f[i]=min(f[i],f[i-a[j]]+1)\)。

\(a\)数组为临时面值数组。

求出f数组之后就枚举到第一个大于n的就行了。

设计一下DFS:

void DFS(int dep,int now,int tmp)

dep:当前枚举了多少数;

now:当前数;

tmp:上一个最大面值。

然后就没了。

2.细节

for(rg int i=now+1;i<=tmp+1;i++){

a[dep]=i;

DFS(dep+1,i,DP(dep));

}

下界的now+1不用说,关键是上界。

i肯定是尽量往大里枚举,

但如果枚举到tmp+2的话中间就会空出一个数,不符合题目要求。

所以此处为tmp+1。(不多不少刚刚好)

2.

题目中没有给出最大面值为多少,所以f数组看着开吧。

3.代码

省去了又臭又长的缺省源。

int n,k,a[50],f[100010],ans[50],maxs;

inline int DP(int x){

memset(f,0x3f,sizeof(f));

f[0]=0;

for(rg int j=1;j<=x;j++){

for(rg int i=a[j];i<=a[x]*n;i++){

f[i]=min(f[i],f[i-a[j]]+1);

}

}

for(rg int i=1;i<=a[x]*n;i++){

if(f[i+1]>n)return i;

}

return a[x]*n;

}

void DFS(int dep,int now,int tmp){

if(dep>k){

if(tmp>maxs){

maxs=tmp;

for(rg int i=1;i<=k;i++){

ans[i]=a[i];

}

}

return;

}

for(rg int i=now+1;i<=tmp+1;i++){

a[dep]=i;

DFS(dep+1,i,DP(dep));

}

}

int main(){

Read(n),Read(k);

DFS(1,0,0);

for(rg int i=1;i<=k;i++){

cout<

}

cout<

cout<

return 0;

}

4.完结撒花

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值