题目链接
题解DFS+动态规划。
整体思路: 第i
个邮票的面值的范围为:value[i] = value[i-1]+1 ~ mx[i-1]+1
,其中value[i]
表示第i
个邮票的面值,mx[i]
表示前i
个邮票能构成的连续最大数;解释一下这个范围,第i
个邮票的面值至少比第i-1
个邮票的面值多1
,且必须要不超过前i-1
个邮票(默认都是最多n
张)所能构成的最大面值+1
,要是大于最大面值+1
就无法满足连续了。 因此,如果我们知道前一个邮票的面值,那么我们就可以推出当前邮票的面值范围,枚举范围内的面值,进行深搜,当找完k
个面值的邮票时,更新一下最大连续数即可。显然,我们现在知道第一个邮票的面值必然是1
,因此,上述的深搜方式确实可以进行。
还有一个问题,如何确定mx[i]
呢? 我们不去直接考虑从前i
种邮票中选取n
张能构成的最大面值,而是考虑前i
种邮票构成面值为j
的最少张数。 即使得到最小张数了,我们如何确定mx[i]
?对于前i
种邮票,我们只需要从小到大遍历面值j
,判断枚举到的j
对应的最少张数是否大于n
(n
如题),只要遇到了大于n
的面值j
,就说明无法用n
张构成面值j
,不满足连续的要求,所以最多也就能构成面值为j-1
了,我们就得到了前i-1
种邮票选取最多n
张所能构成的最大面值,即j-1
。 理解了为什么,接下来讲讲怎么做。 当我们要计算mx[i]
时,其实value[1~i]
都已经在深搜的过程中枚举好了,那我们将求mx[i]
的问题再进行简化。 求已知的若干个数,第i
个数的值为a[i]
,求构成数值为m
的数,最少需要多少个数? 比较经典的dp
吧 , 转移方程为dp[j] = min(dp[j], dp[j-a[i]]+1)
(这是一维的,降维后是这个转移方程) 求mx
也是一样的,我们先通过动态规划求出前i
种邮票能构成面值为j
的最少数量,之后从小到大枚举面值,遇到所需数量大于n
的面值就break
,跳出时的面值-1
即为mx
。
如果看了上面还是没思路,但是还想自己写代码的同学,可以看看下面提示的伪代码。
本题的伪代码:
#include
using namespace std;
const int N = 13*13;
int n, k, ans, res[N], value[N], f[N];
int dp(int x) {
memset(f, 0x3f, sizeof f); // 动规初始化
f[0] = 0;
for(int i = 1;i ans) {
ans = mx;
for(int i = 1;i n>>k;
dfs(1, 0); // 第一个参数是现在要确定第几个邮票的面值,第二个参数是前面的邮票构成的最大连续数是多少
for(int i = 1;i
关注
打赏
最近更新
- 深拷贝和浅拷贝的区别(重点)
- 【Vue】走进Vue框架世界
- 【云服务器】项目部署—搭建网站—vue电商后台管理系统
- 【React介绍】 一文带你深入React
- 【React】React组件实例的三大属性之state,props,refs(你学废了吗)
- 【脚手架VueCLI】从零开始,创建一个VUE项目
- 【React】深入理解React组件生命周期----图文详解(含代码)
- 【React】DOM的Diffing算法是什么?以及DOM中key的作用----经典面试题
- 【React】1_使用React脚手架创建项目步骤--------详解(含项目结构说明)
- 【React】2_如何使用react脚手架写一个简单的页面?