您的位置:首页 > 娱乐 > 八卦 > 邯郸之窗官网_商务服务_网络营销是以什么为中心_网站怎么快速排名

邯郸之窗官网_商务服务_网络营销是以什么为中心_网站怎么快速排名

2025/5/2 12:40:34 来源:https://blog.csdn.net/2302_76739243/article/details/146885451  浏览:    关键词:邯郸之窗官网_商务服务_网络营销是以什么为中心_网站怎么快速排名
邯郸之窗官网_商务服务_网络营销是以什么为中心_网站怎么快速排名

题目一:爬楼梯

问题描述

57. 爬楼梯(第八期模拟笔试)

假设你正在爬楼梯。需要 n 阶你才能到达楼顶。 

每次你可以爬至多m (1 <= m < n)个台阶。你有多少种不同的方法可以爬到楼顶呢? 

注意:给定 n 是一个正整数。

输入描述

输入共一行,包含两个正整数,分别表示n, m

输出描述

输出一个整数,表示爬到楼顶的方法数。

输入示例

3 2

输出示例

3

提示信息

数据范围:
1 <= m < n <= 32;

当 m = 2,n = 3 时,n = 3 这表示一共有三个台阶,m = 2 代表你每次可以爬一个台阶或者两个台阶。

此时你有三种方法可以爬到楼顶。

  1. 1 阶 + 1 阶 + 1 阶段
  2. 1 阶 + 2 阶
  3. 2 阶 + 1 阶

解题步骤

昨天的题目我们已经用二维数组实现了完全背包在排列问题和组合问题上的应用

那么今天我们用一维数组来简化一下方法,使代码更短,思路更清晰

首先审题!(不然就会跟我一样一直AC不了最后发现是n,m搞反了)

要先输入两个整数n,m

一定要看清楚n是总台阶数,m是最大步数

也就是说我们每次可以在1~m中选取,最后总和为n

用完全背包套一下定义就是

现在背包最大容量为n,我们有1~m号物品,价值,重量就是对应索引

所以这一题不需要额外的数组来存储物品价值,重量,一切和 i 表示的一致

动规五部曲

1.确定dp数组下标及含义

i 表示可以从1~i 步中选择

j表示台阶数

dp[i][j]表示每次走1~i阶台阶,到达j的方法有dp[i][j]种

以上是二维数组的定义,那么我们只要去掉i这个维度,就可以变成一维

因为每次加入一种步伐选择,我们的方案数都是在原来的基础上增加的

所以可以使用dp[ j ]来代表台阶为 j 时可选方案有dp[ j ]种

2.初始化

一维dp数组的初始化就很简单了,我们只要让dp[0]=1即可

表示0阶台阶有一种方法,就是不走

3.遍历顺序

从示例来看,当 m = 2,n = 3 时,有三种方法可以爬到楼顶

  1. 1 阶 + 1 阶 + 1 阶段
  2. 1 阶 + 2 阶
  3. 2 阶 + 1 阶

也就是说[1,2],[2,1]是不同组合,我们强调顺序

所以这题属于排列问题

需要先遍历背包容量(也就是台阶数),再遍历物品种类(也就是步伐)

 for(int j=1;j<=n;j++){//在初始化后一个状态开始生成

        for(int i=1;i<=m;i++){//步伐数属于[1,m]闭区间别忘记取等

 4.递推公式

当加入步伐数i时,依旧有两种选择,使用或者不使用

不使用那就是不改变当前状态对一维数组也就不需要更新

使用的话背包容量就要空出相应部分,前提是背包容量足够

if( j >= i ){

        dp[ j ]+=dp[ j-i ];

}

 5.发现错误即时打印dp检查一下!

最后只需要输出dp[n]即可,完整代码如下!

code

#include<bits/stdc++.h>
using namespace std;
int main(){int n,m;cin>>n>>m;vector<int> dp(n+1,0);dp[0]=1;for(int j=1;j<=n;j++){for(int i=1;i<=m;i++){if(j>=i)dp[j]+=dp[j-i];}}cout<<dp[n];return 0;
}

题目二:零钱兑换

问题描述

322. 零钱兑换 - 力扣(LeetCode)

给你一个整数数组 coins ,表示不同面额的硬币;以及一个整数 amount ,表示总金额。

计算并返回可以凑成总金额所需的 最少的硬币个数 。如果没有任何一种硬币组合能组成总金额,返回 -1 。

你可以认为每种硬币的数量是无限的。

示例 1:

输入:coins = [1, 2, 5], amount = 11
输出:3 
解释:11 = 5 + 5 + 1

示例 2:

输入:coins = [2], amount = 3
输出:-1

示例 3:

输入:coins = [1], amount = 0
输出:0

提示:

  • 1 <= coins.length <= 12
  • 1 <= coins[i] <= 231 - 1
  • 0 <= amount <= 104

解题步骤

我们已经做过零钱兑换②

那么这个初代有什么不一样呢?

读题可以发现,这里求的是最少的硬币个数

之前的题目里我们有求背包最大价值,方案数等等

但这个求方案里的元素个数,并且是最小值,还是第一次见

所以递推公式我们需要重新考虑一下,其它小细节也不能放过

例行公事!(这里使用一维数组喽!)

1.确认dp数组下标及含义

dp[j]表示背包容量(硬币总额)为j时,选取物品(硬币)的最少个数,

vector<int >dp(amount+1);

2.初始化

 一维数组,特殊考虑dp[0]

dp[0]表示总和为0时,放硬币的个数,那必然为0

其它值我们应该初始化为不影响寻找最小值的

所以可以在定义时顺手初始化为INT_MAX

vector<int >dp(amount+1,INT_MAX);

dp[0]=0

3.遍历顺序

 由于这一题求的是元素个数,那么它是组合问题也好,排序问题也罢

都不会影响结果

所以先遍历背包再遍历物品,或者先遍历物品再遍历背包都可以

for(int i=0;i<n;i++){

        for(j=0;j<=amount;j++){ // j 的初始值待商榷

 4.递推公式

可以模拟只放第一种硬币来思考一下,

假如第一种硬币面额为2,需要硬币总额为10

那么:

dp[1]=INT_MAX(由于单个面额过大所以放不了,对当前值不做处理,依旧是初始化的INT_MAX),

dp[2]=1

dp[3]=INT_MAX

dp[4]=2

...

假如可以选择面额为2,5的两种硬币,总额依旧为10

那么

dp[1]=INT_MAX(塞不进去保留前面的状态)

dp[2]=1(不能塞5,保留)

dp[3]=INT_MAX(同上)

dp[4]=2(同上)

dp[5]=1=dp[0]+1(放入5需要清空前面的,所以变为dp[0],但我们会假如一枚硬币5,所以+1)

dp[6]=3

....

所以不放/放不进来情况下,dp[j]保持不变

腾出位置放入,dp[j]=dp[j-coins[i]]+1

或许看到这个式子会有疑问,

用j减去coins[i]这个i是当前值(假如当前j=6,coins[i]=4),那怎么不算我减少了2个硬币2呢?

确实,我们从6中腾出4个容量,是取出了2个硬币,加入4又增加了1,最后应该是2个

而dp[6]直接按照公式就是=dp[2]+1=1+1=2

就是当前取出4,被保留的是2状态,这是符合我们的放取逻辑的

最终递推公式为

dp[j]=min(dp[j],dp[j-coins[i]]+1);

填个坑!

此外需要注意的是出现下标为j-coins[i],那么不能数组越界,

所以j的初始值应该设置为j=coins[i]

最后应该返回dp[amount]

但同时题目要求:如果没有任何一种硬币组合能组成总金额,返回 -1 。

那怎么样算是没有组合呢?

当然就是还是初始值,没有发生改变的情况

if(dp[amount]==INT_MAX) return -1;

完整代码如下!

code

class Solution {
public:int coinChange(vector<int>& coins, int amount) {int n=coins.size();vector<int> dp(amount+1,INT_MAX);dp[0]=0;for(int i=0;i<n;i++){for(int j=coins[i];j<=amount;j++){if (dp[j - coins[i]] != INT_MAX) { // 如果dp[j - coins[i]]是初始值则跳过dp[j] = min(dp[j - coins[i]] + 1, dp[j]);}}}if(dp[amount]==INT_MAX) return -1;return dp[amount];}
};

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com