为什么射出的精子里有淡红色| 刺梨果有什么功效| 黑色阔腿裤搭配什么上衣好看| 过梁是什么| 人体由什么组成| 来月经吃什么水果好| 食品级pp材质是什么| x片和ct有什么区别| 大便红褐色是什么原因| 尿蛋白弱阳性什么意思| 花仙子是什么意思| 肝胆科属于什么科| 玫瑰花像什么| 睡眠不足会引起什么症状| 扁桃体肿大吃什么药| 性向是什么意思| apn是什么意思| 痢疾是什么病| 心颤是什么症状| 血脂异常是什么意思| 冉冉是什么意思| 头发长得慢是什么原因| 频繁打嗝是什么原因| 伟五行属性是什么| nb是什么品牌| 孔雀女是什么意思| 阴唇发黑是什么原因| 肺炎吃什么药好得快| 为什么会突然流鼻血| 孕妇嗓子疼可以吃什么药| 县副局长是什么级别| 青稞是什么| ggdb是什么牌子| cs和cf有什么区别| 女鼠和什么属相最配对| 谷氨酰转移酶高是什么病| 身上长湿疹是什么原因导致| 烟草属于什么行业| 脚后跟疼用什么药最好| 第一次什么感觉| 渣滓是什么意思| 布洛芬缓释胶囊有什么副作用| 尿路感染吃什么药| 把脉能看出什么隐私| 泥鳅喜欢吃什么食物| 什么那是什么吧| 角的大小与什么有关与什么无关| 属鼠的本命佛是什么佛| 肋骨骨折吃什么药| 垂问是什么意思| 立夏是什么时候| 啤酒加鸡蛋有什么功效| 沙参长什么样子图片| 5月10号是什么日子| 犀利哥什么意思| 秋五行属什么| 阿尔兹海默症挂什么科| 头晕头重昏昏沉沉是什么原因| 66岁属什么生肖| ut是什么意思| 大腿骨叫什么骨| 女性私下有苦味主要是什么原因| 松鼠喜欢吃什么食物| 女人脚浮肿是什么原因| 耳机戴久了有什么危害| 内膜是什么| 眼睛散光是什么原因造成的| 时蔬是什么意思| 经期上火了吃什么降火| 百合有什么作用| 右手发麻是什么原因| 碳14是检查什么的| 咽炎雾化用什么药最好| 硝化细菌是什么| 胆囊壁增厚是什么意思| 肾不好是什么原因引起的| 脂蛋白a高有什么危害| 胃出血什么症状| 西安有什么山| ca医学代表什么意思| 孕妇鼻炎犯了可以用什么药治疗| 身上出现白块什么原因| Urea医学上是什么意思| me too是什么意思| 淋巴结看什么科| 割包为什么很多人后悔| 淋巴炎吃什么药效果好| 梨涡是什么意思| 牙齿疼痛吃什么药| 中国的国花是什么花| 血压突然升高是什么原因| 太阳五行属什么| 什么降肌酐| pe是什么意思| 什么运动瘦肚子最快| 男生喉结不明显是为什么| 法器是什么意思| 跳舞有什么好处| 痛风是什么| 什么的绽放| 长期做梦是什么原因| 小腿浮肿吃什么药最好| 26岁属什么| 一动就大汗淋漓是什么原因| 青春永驻什么意思| 脸上有痣去医院挂什么科| 急性肠胃炎是什么原因引起的| ser是什么氨基酸| 减脂晚餐吃什么| 经常口腔溃疡挂什么科| 羊水破了什么感觉| 1月3号什么星座| 单元剧是什么意思| 玉是什么结构的字| 什么蛋不能吃| 双子座的幸运色是什么| 隐形眼镜护理液可以用什么代替| hcg偏高是什么原因| 淋巴结发炎吃什么药| 安欣是什么电视剧| rh血型阴性是什么意思| 团长什么级别| 放行是什么意思| 骨蒸潮热是什么意思| 牙疼吃什么食物| 月经量少吃什么药调理| 骨碎补有什么功效| 垂直同步有什么用| 喝什么水最解渴| 茶色尿是什么原因引起的| 阴虚火旺吃什么食物好| 血糖高吃什么水果最好| 爱出者爱返福往者福来是什么意思| 强光斑是什么意思| 8月14是什么星座| 差强人意什么意思| 肝内囊性灶什么意思| 颈椎痛吃什么药| 红薯叶不能和什么一起吃| 正品是什么意思| 怀孕不能吃什么东西| 炖鸡放什么调料| 按摩有什么好处| 惊弓之鸟是什么故事| 生辰八字五行缺什么| 洗手做羹汤是什么意思| 黄色配什么颜色| 老铁是什么意思| 平均血小板体积偏低是什么意思| 现在当兵需要什么条件| 1992是什么年| 缺铁性贫血的人吃什么补血最快| sds是什么| 侄女叫我什么| 斯夫是什么意思| 白鸡蛋是什么鸡下的蛋| 白细胞偏低是什么原因| 怀孕肚皮痒是什么原因| 红薯和什么不能一起吃| 农垦局是什么性质单位| 探病送什么花| 眼睛模糊用什么眼药水| 毛片是什么| 教师的职责是什么| 熙熙攘攘是什么意思| 昆明的别称是什么| 美国人的祖先是什么人| 脚扭了挂什么科| 不打自招是什么生肖| 青蛙靠什么呼吸| 点了斑不能吃什么| 道和集团是干什么的| 胆囊息肉是什么| 草鱼喜欢吃什么| 唐三藏的真名叫什么| 1月16日什么星座| 蓝脸的窦尔敦盗御马是什么歌| 两个方一个土读什么| 鲜卑族现在是什么族| 老是头疼是什么原因| 吃丝瓜有什么好处| 舌系带长有什么影响吗| 淋巴肿了吃什么消炎药| 随诊是什么意思| 什么方法避孕最安全有效| 相思成疾是什么意思| 阴道里面有个肉球是什么| 物色什么意思| 一拃长是什么意思| 兆是什么意思| 85年的属什么| 喝什么茶降血糖| 琀是什么意思| 楼房风水主要看什么| 碧螺春属于什么茶类| 回民不能吃什么| 血糖高可以吃什么水果| 粉红色泡沫痰见于什么病| 凌晨两点是什么时辰| 男人更年期吃什么药| 桑树枝煮水有什么功效| 平均红细胞体积偏高是什么意思| 盔甲是什么意思| 腐男是什么意思| 输卵管造影什么时候检查最好| 小儿割包皮挂什么科| 六月是什么星座| 淡淡的什么| 五行属性是什么| 步摇是什么| 腰疼什么原因| c反应蛋白是什么| 什么的早晨| 网络绿茶是什么意思| 什么是六合| 养胃喝什么| 仙逝是什么意思| 青柠檬和黄柠檬有什么区别| 中药什么时候喝| 吃什么可以解酒| 一什么骆驼| 什么心什么心| 口疮反复发作什么原因| 晚上睡觉容易醒是什么原因| 肾怕什么| 家乡是什么意思| 婀娜多姿是什么意思| 1月26号是什么星座| 妤字属于五行属什么| 李子吃多了有什么坏处| 女生阴道长什么样| 都市丽人什么意思| 菲律宾货币叫什么| 抗ccp抗体高说明什么| 4月15日是什么日子| 中药用什么锅熬效果最佳| 十二是什么意思| 男属猴和什么属相最配| 肆无忌惮的意思是什么| 子宫内膜厚是什么原因| 修罗道是什么意思| 莞式服务是什么| 什么帽子不能戴| 什么牛排最好吃| 蘑菇什么季节长出来| 早睡有什么好处| 双肾实质回声增强是什么意思| 黄精泡水喝有什么功效| 虾青素有什么作用| 婴儿增强免疫力吃什么| 更年期吃什么好| 舌头红是什么原因| 脑委缩吃什么药能空制| 梦见穿裤子是什么意思| 石英岩玉是什么| 蕾丝是什么| 包皮过长是什么样的| 为什么一年比一年热| 20分贝相当于什么声音| 切除胆囊有什么影响| 脚腿肿是什么原因引起的| 应无所住而生其心什么意思| 耳朵响是什么原因引起的| 嘴唇发紫发黑是什么原因| 百度

暂住证过期如何申领居住证

百度   也有媒体指出,商家的溢价行为本身并没有问题,问题在于这种溢价是否透明。

53.完全背包【模版】

完全背包
你有一个背包,最多能容纳的体积是V。

现在有n种物品,每种物品有任意多个,第i种物品的体积为vivi??,价值为wiwi?。

(1)求这个背包至多能装多大价值的物品?

(2)若背包恰好装满,求至多能装多大价值的物品?

输入描述:
第一行两个整数n和V,表示物品个数和背包体积。

接下来n行,每行两个数vivi?和wiwi?,表示第i种物品的体积和价值。

1≤n,V≤10001≤n,V≤1000

输出描述:
输出有两行,第一行输出第一问的答案,第二行输出第二问的答案,如果无解请输出0。
image.png
image.png
dp[i] [j]表示:从前i个物品中选,总体积不超过j,所有选法中,最大的价值image.png
image.png
那么最终的动态规划表达式就是在合格
image.png
i位置存在选和不选,选的话存在选多少个的情况

初始化可以不用,都初始化为0就行了

这个第一问的问题是从所有的物品中去选,求这个背包至多能装多大价值的物品,就是最大价值不超过V
所以这个的返回值就是dp[n] [v]

第二问是总体积一定要等于j的
若背包恰好装满,求至多能装多大价值的物品?
dp[i] [j]表示:从前i个物品中选,总体积恰好是j,所有选法中,最大的价值
我们在一开始初始化的时候加上一个状态,就是-1,-1就是表示当前的这个物品是不能凑到j-v[i]的体积的

就是dp[i] [j-v[i]]!=-1的情况才能进行后续的操作

初始化的话我们还是仅仅只是需要修改第一行就行了,初始化如下
image.png
返回值的话就是dp[n][V]== -1?0:dp[n][v]
如果是-1的话,那么就返回0,如果不是-1的话那么就返回dp[n] [v]就行了

#include <iostream>

#include<string.h>

using namespace std;

  

const int N=1010;

  

int n,V,v[N],w[N];

int dp[N][N];

int main()

{

? ? //读入数据

? ? cin>>n>>V;

? ? for(int i=1;i<=n;i++)

? ? {

? ? ? ? cin>>v[i]>>w[i];

? ? }

  

? ? //解决第一问

? ? //这里我们是不需要进行初始化操作的

? ? for(int i=1;i<=n;i++)

? ? {

? ? ? ? for(int j=0;j<=V;j++)//我们从0开始进行计数,因为我们是没有初始化第一列的

? ? ? ? {

? ? ? ? ? ? dp[i][j]=dp[i-1][j];//就是i位置不选

? ? ? ? ? ? if(j-v[i]>=0)dp[i][j]=max(dp[i][j],dp[i][j-v[i]]+w[i]);//我们这里是完全背包,所以我们这里是dp[i]的,我们这里就是选择i位置的,选多少个i位置的物品,那么总体归纳起来就是dp[i][j-v[i]]+w[i]

? ? ? ? }

? ? }

? ? cout<<dp[n][V]<<endl;

  

? ? //我们现在需要重新用dp表,所以需要将这个进行清空的操作

? ? memset(dp,0,sizeof dp);

? ? //初始化,我们需要将第一行除了第一个位置都初始化为-1,-1这个状态表示的就是这个位置是不能凑到j-v[i]的,就是不行的

? ? for(int i=1;i<=V;i++)dp[0][i]=-1;//都初始化为-1

  

? ? for(int i=1;i<=n;i++)

? ? {

? ? ? ? for(int j=0;j<=V;j++)//我们从0开始进行计数,因为我们是没有初始化第一列的

? ? ? ? {

? ? ? ? ? ? dp[i][j]=dp[i-1][j];//就是i位置不选

? ? ? ? ? ? //这里的话我们因为需要恰好凑到j,所以我们在使用dp[i][j-v[i]]+w[i]这个状态的时候,我们需要判断下这个状态是否存在

? ? ? ? ? ? if(j-v[i]>=0&&dp[i][j-v[i]]!=-1)dp[i][j]=max(dp[i][j],dp[i][j-v[i]]+w[i]);//我们这里是完全背包,所以我们这里是dp[i]的,我们这里就是选择i位置的,选多少个i位置的物品,那么总体归纳起来就是dp[i][j-v[i]]+w[i]

? ? ? ? }

? ? }

? ? //我们输出结果的时候是不能进行直接输出的,我们是需要进行判断操作的

? ? cout<<(dp[n][V]==-1?0:dp[n][V])<<endl;

  

? ? return 0;

}

这里进行下总结:
第一问是求这个背包至多能装多大价值的物品
就是体积j不超过V就行了,
我们完全背包的物品是有个数的,我们可以挑选i这个位置的物品,也是可以不挑选的,可以挑选1个,2个甚至k个

这个就是和我们01背包是截然不同的区别

那么我们i位置物品不选的情况就是
image.png
如果我们选择了i位置的话,存在选多少个的情况,那么都包含在下面的dp状态中了
image.png
为什么是是这样的,可以参考下面的图片
image.png

第二问是若背包恰好装满,求至多能装多大价值的物品
就是说我们的j要恰好等于V
所以我们是需要在初始化的时候加上-1这个状态的
就是表示这个dp位置是不能凑到dp[i] [j-v[i]]的,所以我们 就得进行一个判断了,看看这个位置是否为-1,必须不等于-1才能进行后面的操作

返回值也是的,我们需要判断这个位置是否为-1,如果是-1的话就返回0,如果不是-1的话就正常返回值就行了

下面是进行空间优化后的代码,将横坐标都删除了
完全背包是从左往右进行遍历的
01背包是从右往左进行遍历的

image.png

#include <iostream>

#include<string.h>

using namespace std;

  

const int N=1010;

  

int n,V,v[N],w[N];

int dp[N];

int main()

{

? ? //读入数据

? ? cin>>n>>V;

? ? for(int i=1;i<=n;i++)

? ? {

? ? ? ? cin>>v[i]>>w[i];

? ? }

  

? ? //解决第一问

? ? //这里我们是不需要进行初始化操作的

? ? for(int i=1;i<=n;i++)

? ? {

? ? ? ? for(int j=v[i];j<=V;j++)//我们从0开始进行计数,因为我们是没有初始化第一列的

? ? ? ? {

? ? ? ? ? ? if(j-v[i]>=0)dp[j]=max(dp[j],dp[j-v[i]]+w[i]);//我们这里是完全背包,所以我们这里是dp[i]的,我们这里就是选择i位置的,选多少个i位置的物品,那么总体归纳起来就是dp[i][j-v[i]]+w[i]

? ? ? ? }

? ? }

? ? cout<<dp[V]<<endl;

  

? ? //我们现在需要重新用dp表,所以需要将这个进行清空的操作

? ? memset(dp,0,sizeof dp);

? ? //初始化,我们需要将第一行除了第一个位置都初始化为-1,-1这个状态表示的就是这个位置是不能凑到j-v[i]的,就是不行的

? ? for(int i=1;i<=V;i++)dp[i]=-1;//都初始化为-1

  

? ? for(int i=1;i<=n;i++)

? ? {

? ? ? ? for(int j=v[i];j<=V;j++)//我们从0开始进行计数,因为我们是没有初始化第一列的

? ? ? ? {

? ? ? ? ? ? //这里的话我们因为需要恰好凑到j,所以我们在使用dp[i][j-v[i]]+w[i]这个状态的时候,我们需要判断下这个状态是否存在

? ? ? ? ? ? if(dp[j-v[i]]!=-1)dp[j]=max(dp[j],dp[j-v[i]]+w[i]);//我们这里是完全背包,所以我们这里是dp[i]的,我们这里就是选择i位置的,选多少个i位置的物品,那么总体归纳起来就是dp[i][j-v[i]]+w[i]

? ? ? ? }

? ? }

? ? //我们输出结果的时候是不能进行直接输出的,我们是需要进行判断操作的

? ? cout<<(dp[V]==-1?0:dp[V])<<endl;

  

? ? return 0;

}

可以对比,在空间优化方面,01背包和完全背包就内层for循环不一样

其实还有一个优化的点
我们在循环中加上这么一个状态就是想让后面的那个状态不生效,必须满足条件才能生效
只有合法才能进行使用
image.png
只要我们后面的那个状态足够小的话,那么我们就可以不加后面的那个状态以及前面的判断

这里的话我们是将无效的状态设置为-1,那么我们这里可以设置为无穷小(0x3f3f3f3f),那么我们就可以不用加这些判断条件了,
改动代码如下:返回值和判断条件改动了

#include <iostream>

#include<string.h>

using namespace std;

  

const int N=1010;

  

int n,V,v[N],w[N];

int dp[N];

int main()

{

? ? //读入数据

? ? cin>>n>>V;

? ? for(int i=1;i<=n;i++)

? ? {

? ? ? ? cin>>v[i]>>w[i];

? ? }

  

? ? //解决第一问

? ? //这里我们是不需要进行初始化操作的

? ? for(int i=1;i<=n;i++)

? ? {

? ? ? ? for(int j=v[i];j<=V;j++)//我们从0开始进行计数,因为我们是没有初始化第一列的

? ? ? ? {

? ? ? ? ? ? if(j-v[i]>=0)dp[j]=max(dp[j],dp[j-v[i]]+w[i]);//我们这里是完全背包,所以我们这里是dp[i]的,我们这里就是选择i位置的,选多少个i位置的物品,那么总体归纳起来就是dp[i][j-v[i]]+w[i]

? ? ? ? }

? ? }

? ? cout<<dp[V]<<endl;

  

? ? //我们现在需要重新用dp表,所以需要将这个进行清空的操作

? ? memset(dp,0,sizeof dp);

? ? //初始化,我们需要将第一行除了第一个位置都初始化为-1,-1这个状态表示的就是这个位置是不能凑到j-v[i]的,就是不行的

? ? for(int i=1;i<=V;i++)dp[i]=-0x3f3f3f3f;//都初始化为-1

  

? ? for(int i=1;i<=n;i++)

? ? {

? ? ? ? for(int j=v[i];j<=V;j++)//我们从0开始进行计数,因为我们是没有初始化第一列的

? ? ? ? {

? ? ? ? ? ? //这里的话我们因为需要恰好凑到j,所以我们在使用dp[i][j-v[i]]+w[i]这个状态的时候,我们需要判断下这个状态是否存在

? ? ? ? ? ? dp[j]=max(dp[j],dp[j-v[i]]+w[i]);//我们这里是完全背包,所以我们这里是dp[i]的,我们这里就是选择i位置的,选多少个i位置的物品,那么总体归纳起来就是dp[i][j-v[i]]+w[i]

? ? ? ? }

? ? }

? ? //我们输出结果的时候是不能进行直接输出的,我们是需要进行判断操作的

? ? cout<<(dp[V]<0?0:dp[V])<<endl;

  

? ? return 0;

}

54.零钱兑换

零钱兑换
给你一个整数数组?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

dp[i] [j]表示:从前i个硬币中挑选,总和正好等于j,所有的选法中的最少的硬币个数image.png
因为这里我们需要满足总和正好等于j的情况,所以的话我们是需要初始化一种情况来表示这种选法是不合规的
我们直接将第一行从第二个格子开始初始化为无穷大就行了 0x3f3f3f3f
我们这里是求最少的硬币个数,就是最小值了image.png
返回值,避免了无效的dp
image.png

class Solution

{

public:

? ? int coinChange(vector<int>& coins, int amount)

? ? {

? ? ? ? const int INF=0x3f3f3f3f;

? ? ? ? int n=coins.size();

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

? ? ? ? //初始化的话,从第一个第二个格子开始都初始化为无穷大就行了

? ? ? ? for(int i=1;i<=amount;i++)dp[0][i]=INF;

  

? ? ? ? for(int i=1;i<=n;i++)

? ? ? ? {

? ? ? ? ? ? for(int j=0;j<=amount;j++)//我们并没有初始化第一列,所以是从0开始的

? ? ? ? ? ? {

? ? ? ? ? ? ? ? dp[i][j]=dp[i-1][j];//这种就是i位置不选的情况

  

? ? ? ? ? ? ? ? //下面的就是选择i位置的,并且带有数量的,就是选择了多少个的

? ? ? ? ? ? ? ? if(j-coins[i-1]>=0)dp[i][j]=min(dp[i][j],dp[i][j-coins[i-1]]+1);//因为我们加了一行和一列,所以下标映射的时候是需要进行-1操作的

? ? ? ? ? ? }

? ? ? ? }

? ? ? ? return (dp[n][amount]>=INF?-1:dp[n][amount]);//如果这个dp状态大于INF的话,那么就返回-1,如果不是的话那么就直接返回dp[n][amount]

? ? }

};

下面是空间优化的代码,将横坐标删除了

class Solution

{

public:

? ? int coinChange(vector<int>& coins, int amount)

? ? {

? ? ? ? const int INF=0x3f3f3f3f;

? ? ? ? int n=coins.size();

? ? ? ? vector<int>dp(amount+1);

? ? ? ? //初始化的话,从第一个第二个格子开始都初始化为无穷大就行了

? ? ? ? for(int i=1;i<=amount;i++)dp[i]=INF;

  

? ? ? ? for(int i=1;i<=n;i++)

? ? ? ? {

? ? ? ? ? ? for(int j=coins[i-1];j<=amount;j++)//我们并没有初始化第一列,所以是从0开始的

? ? ? ? ? ? {//优化版本的,我们的j直接从coins[i-1]开始进行遍历操作

  

? ? ? ? ? ? ? ? //下面的就是选择i位置的,并且带有数量的,就是选择了多少个的

? ? ? ? ? ? ? ? dp[j]=min(dp[j],dp[j-coins[i-1]]+1);//因为我们加了一行和一列,所以下标映射的时候是需要进行-1操作的

? ? ? ? ? ? }

? ? ? ? }

? ? ? ? return (dp[amount]>=INF?-1:dp[amount]);//如果这个dp状态大于INF的话,那么就返回-1,如果不是的话那么就直接返回dp[n][amount]

? ? }

};

55.零钱兑换 II

零钱兑换 II
给你一个整数数组?coins?表示不同面额的硬币,另给一个整数?amount?表示总金额。

请你计算并返回可以凑成总金额的硬币组合数。如果任何硬币组合都无法凑出总金额,返回?0?。

假设每一种面额的硬币有无限个。

题目数据保证结果符合 32 位带符号整数。

示例 1:

输入: amount = 5, coins = [1, 2, 5]
输出: 4
解释: 有四种方式可以凑成总金额:
5=5
5=2+2+1
5=2+1+1+1
5=1+1+1+1+1

示例 2:

输入: amount = 3, coins = [2]
输出: 0
解释: 只用面额 2 的硬币不能凑成总金额 3 。

示例 3:

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

提示:

  • 1 <= coins.length <= 300
  • 1 <= coins[i] <= 5000
  • coins?中的所有值?互不相同
  • 0 <= amount <= 5000

dp[i] [j]表示:从前i个物品中挑选,总体积不超过j,所有选法中,最大的价值

上面是固定的思路

下面是我们这道题的
dp[i] [j]表示:从前i个硬币中挑选,总和正好等于j,一共有多少种选法image.png
我们初始化的话就是直接将第一行的第一个格子初始化为1就行了,其他的都初始化为0

class Solution

{

public:

? ? int change(int amount, vector<int>& coins)

? ? {

? ? ? ? int n = coins.size();

? ? ? ? vector<double> dp(amount + 1, 0); ?// 初始化 dp 数组,并将所有值设为 0

? ? ? ? dp[0] = 1; ?// 组合金额为 0 时,只有 1 种方式(即不选任何硬币)

? ? ? ? for (int i = 0; i < n; i++) ?// 遍历每个硬币

? ? ? ? {

? ? ? ? ? ? for (int j = coins[i]; j <= amount; j++) ?// 从当前硬币的面值开始,更新 dp 数组

? ? ? ? ? ? {

? ? ? ? ? ? ? ? dp[j] += dp[j - coins[i]]; ?// 更新组合数

? ? ? ? ? ? }

? ? ? ? }

? ? ? ? return dp[amount]; ?// 返回组合成目标金额 amount 的方案数

? ? }

};

这里的话我们是需要将dp表用double类型进行存储的,不然的话数据太大是会出现报错的

这里的代码我们直接展示空间优化后的代码的,就是删除了横坐标后的

55.完全平方数

完全平方数
给你一个整数?n?,返回?和为?n?的完全平方数的最少数量?。

完全平方数?是一个整数,其值等于另一个整数的平方;换句话说,其值等于一个整数自乘的积。例如,149?和?16?都是完全平方数,而?3?和?11?不是。

示例?1:

输入: n = 12
输出: 3
解释:12 = 4 + 4 + 4

示例 2:

输入: n = 13
输出: 2
解释:13 = 4 + 9

让我们在一堆数中挑几个数,然后达到我们的总和
并且一个数是可以挑好几次的

所以这个题的话就满足了完全背包的问题

dp[i] [j]表示:从前i个物品中挑选,总体积不超过j,所有选法中,最大的价值

那么我们这个题的即是
dp[i] [j]:从前i个完全平方数中挑选,总和正好等于i,所有选法中,最小的数量

image.png
因为我们是需要使用到min求出最小的数量的,所以我们初始化的时候第一行的第一个格子初始化为0,其他的都初始化为无穷大,让他们不满足要求的参与不了这个比较

返回值的话如下:
因为如果给到我们的是13的话,那么我们只需要x^2<13

image.png

class Solution {

public:

? ? int numSquares(int n)

? ? {

? ? ? ? int m=sqrt(n);//根号n的结果

? ? ? ? vector<vector<int>>dp(m+1,vector<int>(n+1));//规模就是根号n+1,m+1

  

? ? ? ? //初始化

? ? ? ? //除了第一个位置其他都初始化为无穷大

? ? ? ? for(int i=1;i<=n;i++)dp[0][i]=0x3f3f3f3f;//初始化为无穷大就行了,不参与最小值比较

? ? ? ? for(int i=1;i<=m;i++)

? ? ? ? {

? ? ? ? ? ? for(int j=1;j<=n;j++)

? ? ? ? ? ? {

? ? ? ? ? ? ? ? dp[i][j]=dp[i-1][j];//这个就是i位置不选的情况

? ? ? ? ? ? ? ? if(j>=i*i)dp[i][j]=min(dp[i][j],dp[i][j-i*i]+1);

? ? ? ? ? ? }

? ? ? ? }

? ? ? ? return dp[m][n];

? ? }

};

接下来我们进行空间优化操作

class Solution {

public:

? ? int numSquares(int n)

? ? {

? ? ? ? int m=sqrt(n);//根号n的结果

? ? ? ? vector<int>dp(n+1);//规模就是根号n+1,m+1

  

? ? ? ? //初始化

? ? ? ? //除了第一个位置其他都初始化为无穷大

? ? ? ? for(int i=1;i<=n;i++)dp[i]=0x3f3f3f3f;//初始化为无穷大就行了,不参与最小值比较

? ? ? ? for(int i=1;i<=m;i++)

? ? ? ? {

? ? ? ? ? ? for(int j=i*i;j<=n;j++)

? ? ? ? ? ? {

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

? ? ? ? ? ? }

? ? ? ? }

? ? ? ? return dp[n];

? ? }

};
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Undoom

感谢啦

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值
点灯是什么意思 面霜和乳液有什么区别 孕妇不吃饭对胎儿有什么影响 普拉提是什么意思 嘴巴干是什么原因
增强免疫力的针叫什么 梦见大棺材是什么预兆 九头身是什么意思 什么样的人着床晚 猫头鹰属于什么科
老鼠属于什么类动物 血氧饱和度是什么意思 chemical是什么意思 子鱼是什么鱼 王字加一笔是什么字
梦见狗是什么意思 尿黄什么原因 乳腺癌吃什么水果好 肝经湿热吃什么中成药 梦见老公怀孕什么预兆
什么 姿势 最深hcv8jop7ns7r.cn 1.9号是什么星座baiqunet.com 公务员是什么编制hcv8jop7ns4r.cn 格桑花是什么意思hcv9jop6ns9r.cn 阿迪达斯和三叶草有什么区别hcv8jop7ns1r.cn
浮生若梦是什么意思hcv8jop7ns8r.cn 农历6月是什么月travellingsim.com 市政府秘书长什么级别hcv8jop2ns5r.cn 总是心慌是什么原因hcv9jop7ns3r.cn 小猫能吃什么水果hcv7jop6ns1r.cn
hpv是什么病毒hcv8jop7ns2r.cn hb是什么意思hcv8jop6ns6r.cn 手心红是什么原因bfb118.com 荔枝补什么hcv8jop4ns8r.cn 梦见打老虎是什么预兆hcv9jop4ns4r.cn
老出虚汗是什么原因jiuxinfghf.com 肠易激综合征吃什么药hcv9jop3ns0r.cn 士官是什么级别hcv8jop9ns6r.cn 27年属什么生肖hcv7jop9ns1r.cn 全科医生是什么意思hcv9jop4ns4r.cn
百度