【算法每日一练]-动态规划 (保姆级教程 篇15)#动物 #赶deadline #page #构造字符串

目录

今日知识点:

01背包的路径输出

计算位和的数位dp

不用管字符串,只需要看好约束dp转移的变量

动物

 赶deadline

page 

构造字符串 


        

        

动物

有某类动物,可以在农场待n天,每天最多增加一只动物,第i天到来的动物每天要吃的粮食为c[i],现在初始粮食是X,问在每天动物尽可能多的情况下最多容纳多少只动物?

输入:             输出:

3 4                        2

1 1 1

思路:

如果一直考虑每天的食量的话,这道题就不好做了。其实换个角度想一下:

动物来的时间是确定的,那么动物一共吃掉的食物也就确定了,那么者就转化成了01背包问题。

X是背包容量,每只动物的总食量是体积,价值就是1.

#include <bits/stdc++.h>
using namespace std;
int a[1005],f[100005],n,x;
int main(){
	cin>>n>>x;
	for(int i=1;i<=n;i++){
		cin>>a[i];
		a[i]*=(n-i+1);
	}
	for(int i=1;i<=n;i++)
	for(int j=x;j>=a[i];j--)
		f[j]=max(f[j],f[j-a[i]]+1);
	cout<<f[x];
}

        

        

 赶deadline

输入:                                 输出:157
4 1000                                            2 3 4
50 500
75 400
60 300
22 200

         

 思路:

还是一道01背包。不过要输出路径,或者说输出拿到的物品。

举个例子把:

物品编号:       物品体积:       物品价值:

1 2 3 4              2 3 4 5              3 4 5 6

我们的背包转移情况如下图:

dp[i][j]=max(dp[i-1][j],dp[i-1][j-w]+v)

也就是说以蓝色格子为例:仅可以从正上方[1][3]或[1][0]转移过来(如图)。

那么也就是说那 如果f[2][3]和f[1][3]相等,说明没有拿第2个物品;否则就是拿了第2个物品,此时转移到f[1][3-w2]即f[1][0]。

        

 那么整个回溯过程如下面的草图。

每个格子[i][j]都只有两种选择要么是(不拿这个物品)向上走[i-1][j],要么是(拿这个物品) 走到f[i-1][j-w]。这样就能输出整个物品的装入情况了。

 

但是我的不是这么写的。因为是基于一维的背包。直接标记转移更新的就行,对于那些没有放入的物品,我们直接不去标记,这样也能直接找到回溯路径。(可以认为是上图中的取物品的为1,不取物品的为0)

       代码 部分:

#include <bits/stdc++.h>
using namespace std;
const int N=1e4+5;
int t,n,w[N],v[N],f[N],pa[N][N],ans[N];
int main(){
	cin>>n>>t;
	for(int i=1;i<=n;i++)
		cin>>v[i]>>w[i];
	for(int i=1;i<=n;i++)
	for(int j=t;j>=w[i];j--)
		if(f[j-w[i]]+v[i]>f[j]){
			f[j]=f[j-w[i]]+v[i];
			pa[i][j]=1;
		}
	cout<<f[t]<<'\n';
	int i=n,j=t,cnt=0;
	while(i>=1&&j){
		if(pa[i][j]){
			ans[cnt++]=i;
			j-=w[i];
		}
		i--;
	}
	for(int k=cnt-1;k>=0;k--){
		cout<<ans[k]<<" ";
	}	
}

        

       

page 

思路:

一道数位dp题。(卡了我好久)
和之前一样,我最开始定义的是f[3][2]代表200~299的数字。

然后转移方程:f[i][j]=f[i-1][0~9]+j*pow(10,i-1),然后再求cal(n)的时候就发现不太好求了。

因为之前的cal过程是:

外层num[i]从高位到低位取数,里面0~num[i]-1全部加起来。然后逐渐发现不对劲……

最高位的数字一直在丢,没有加上去。导致结果不对。

最后,越写越丑,干脆不写了。

        

正确做法是可以直接的定义f[3][2]代表000~299的数字。

计算f[i][j]的转移方程是这样的:

举个例子:0~7999 即f[4][7]。

f[4][7]=7*10^3+f[4][9]+f[4][0]即:

0~7999=7000+0~6999+0~0999

故:f[i][j]=j*10^(i-1)+f[i][j-1]+f[i][0]

然后求cal(n):

求0~7213

0~7213=0~6999+7*214+0~213(对1000取模就行了)

0~213=0~199+2*14+0~13     (对100取模就行了)

0~13=0~9+1*4+0~3

外层num[i]从高位到低位取数,高位以下求和,然后计算高位数的次数,进入下循环。

终于结束了!!!!!!

        
感悟就是:初始化的转移方程最终求解cal(n)拆分方式的都至关重要。要亲自模拟一下。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int n,m;
ll f[11][10];//f[i][j]表示数字长度为i且最大到以j开头的数字对应的答案数  eg:f[3][2]代表000~299的数字
void init(){
	for(int i=1;i<11;i++){
		f[i][0]=f[i-1][9];
		for(int j=1;j<=9;j++){
			f[i][j]=j*pow(10,i-1)+f[i][j-1]+f[i][0];
		}
	}
}


void cal(int x){
	vector<int>num;int y=x;
	while(x) num.push_back(x%10),x/=10;
	ll ans=0;
	for(int i=num.size()-1;i>=0;i--){
		int t=num[i];
		if(!t) continue;
		ans+=f[i+1][t-1]+(y%int(pow(10,i))+1)*t;
	}
	cout<<ans;
}
int main(){
	cin>>n;
	init();
	cal(n);
}

最后再说一下为什么这次换了这种定义方式:

因为这里不需要内这些内部的数进行处理。直接整体处理就行了。定义成f[i][j]表示i长度,j为最大开头的情况数; 但是之前的都是需要看开头数字的,所有只能定义成f[i][j]表示以i长度,j开始的数字的情况数。 

        

        

构造字符串 

用a,b,c来构造一个长n的字符串,要求:不能有连续三个相同的相邻,如aaa。问有多少种构造方法?

输入:
2
30
5000

思路:

初看还挺简单的,然后设置f[i][j]表示i长度,j结尾的方案数。然后还要考虑有几个相邻,开3维吗?

其实完全不用,a,b,c我们完全不需要管他们,只需要记录已经有几个相邻就行了。因为我们的转移仅仅受到相邻多少个相同的元素的约束。

那就直奔主题吧。设置f[i][1]表示长度i,结尾没有两个相同元素相邻;f[i][0]表示长度i,结尾有两个相同元素相邻;(哈哈哈,根本不存在有3个结尾相邻的情况,所以到0,1就足够了)

转移方程:f[i][0]=f[i-1][1]

f[i][1]=f[i-1][0]+f[f-1][1]

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll mod=1e9+7;
ll x,n,f[100005][2];
int main(){
	f[1][0]=0;f[1][1]=3;
	for(int i=2;i<=100000;i++){
		f[i][0]=f[i-1][1];
		f[i][1]=2*(f[i-1][0]+f[i-1][1])%mod;
	}
	cin>>x;
	while(x--){
		cin>>n;
		cout<<(f[n][0]+f[n][1])%mod<<'\n';
	}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/294116.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Android开发,jni,ndk开发,调用fmod音频库,音效引擎库

文章目录 Android开发&#xff0c;jni&#xff0c;ndk开发&#xff0c;调用fmod音频库&#xff0c;音效引擎库1.fmod介绍2.cmake3.C代码实践 Android开发&#xff0c;jni&#xff0c;ndk开发&#xff0c;调用fmod音频库&#xff0c;音效引擎库 1.fmod介绍 https://www.fmod.c…

前端常用的几种算法的特征、复杂度、分类及用法示例演示

算法&#xff08;Algorithm&#xff09;可以理解为有基本运算及规定的运算顺序所构成的完整的解题步骤&#xff0c;或者看成按照要求设计好的有限的确切的计算序列&#xff0c;并且这样的步骤和序列可以解决一类问题。算法代表着用系统的方法描述解决问题的策略机制&#xff0c…

两整数之和 -- 位运算

个人主页&#xff1a;Lei宝啊 愿所有美好如期而遇 本题链接 力扣&#xff08;LeetCode&#xff09; 输入描述 输入两个要相加的数&#xff0c;a和b 输出描述 返回a和b的和&#xff0c;这里其实直接return ab; 直接就过了&#xff0c;但是人题目要求还是给点面子~ 算法…

mariadb实现主从同步

准备两台服务器 Mariadb-Master&#xff1a;192.168.44.150 Mariadb-Backup&#xff1a;192.168.44.148 安装mariadb&#xff1a; https://blog.csdn.net/qq_50247813/article/details/135402502?spm1001.2014.3001.5502 组从复制原理如下 修改主数据库配置如下 vi /etc/my.…

钼铁,需求量将推动市场进入新一轮发展浪潮

钼铁是一种重要的冶金原料&#xff0c;广泛用于制造高速钢、不锈钢、合金钢、特殊钢等钢材&#xff0c;并且被广泛应用于核工业、电子工业、航空航天等高技术产业领域。随着钢铁市场的不断发展&#xff0c;钼铁市场也逐渐壮大&#xff0c;下面将从全球市场和中国市场分析其发展…

自学 c++ 要掌握哪些技巧和方法?

自学 c 要掌握哪些技巧和方法&#xff1f; 在开始前我有一些资料&#xff0c;是我根据网友给的问题精心整理了一份「C的资料从专业入门到高级教程」&#xff0c; 点个关注在评论区回复“888”之后私信回复“888”&#xff0c;全部无偿共享给大家&#xff01;&#xff01;&…

大模型在现代应用中的多元实例

目录 前言1 GPT-3、GPT-3.5、GPT-4&#xff1a;自然语言处理的新纪元1.1 GPT-3与传统NLP方法的区别1.2 GPT-3.5 和 GPT-4 的进展1.3 技术背后的革新 2 自然语言转换为Python代码2.1 简介2.2 技术原理2.3 应用和优势 3 DALL-E 2&#xff08;5B&#xff09;图像生成3.1 简介3.2 技…

LauraGPT

git&#xff1a;https://github.com/alibaba-damo-academy/FunCodec 文章目录 model archAudioTokenizermodel init model arch text-embedding 用千问的模型参数初始化&#xff1b;AudioEncoder用asr-conformer的参数初始化&#xff1b;所有的参数都参与更新&#xff0c;除了C…

【动态规划】C++算法:115.不同的子序列

作者推荐 【动态规划】【字符串】扰乱字符串 本文涉及的基础知识点 动态规划 LeetCode115 不同的子序列 给你两个字符串 s 和 t &#xff0c;统计并返回在 s 的 子序列 中 t 出现的个数&#xff0c;结果需要对 109 7 取模。 示例 1&#xff1a; 输入&#xff1a;s “rab…

如何让CHAT使用python绘制概率密度图像?

问CHAT&#xff1a;用python绘制概率密度图像 CHAT回复&#xff1a;你可以使用Python的matplotlib库和numpy库进行概率密度的绘制。 以下是一个简单的例子&#xff1a; python import numpy as np import matplotlib.pyplot as plt #随机生成1000个正态分布的数 data np.rand…

无法开机报 不可恢复的错误:securityagent无法创建所要求的机制Teamviewerauthplugin:start

无法开机报 不可恢复的错误&#xff1a;securityagent无法创建所要求的机制Teamviewerauthplugin:start 初步判断很有可能是TeamViewer的某个启动项或者签名书没有&#xff0c; 导致在预加载的时候无法加载TeamViewer。 然后出现这个情况有一个前提&#xff0c;那就是你用了第三…

Linux_CentOS_7.9配置时区及NTPdate同步之简易记录

前言&#xff1a;ntpdate命令来自英文词组”NTPdate“的拼写&#xff0c;其功能是用于设置日期和时间。ntpdate命令能够基于NTP协议设置Linux系统的本地日期和时间&#xff0c;利用NTP服务的时钟过滤器来选择最优方案&#xff0c;大大提高了可靠性和精度&#xff0c;让系统时间…

【RabbitMQ】1 消息中间件MQ概述

目录 什么是消息中间件为什么使用消息中间件流量削峰应用解耦异步处理 主流消息中间件及选型选取原则RabbitMQRocketMQKafka如何选择 消息中间件应用场景电商秒杀案例拉勾B端C端数据同步案例支付宝购买电影票 什么是消息中间件 维基百科对消息中间件的解释&#xff1a;面向消息…

宽压输入1.5KV隔离直流高压输出电源模块

GRC系列低成本小体积宽电压输入隔离高压模块电源&#xff0c;是一款业界的隔离稳压型DC-DC高电压转换器&#xff0c;可在宽范围波动的不稳定电压输入环境中运行&#xff0c;通过模块的内部调整电路可以生成隔离稳压的直流高电压输出。产品外壳采用铝壳喷塑防腐设计&#xff0c;…

栈的数据结构实验报告

一、实验目的&#xff1a; 1、理解栈的定义&#xff1b; 2、利用栈处理实际问题。 二、实验内容&#xff08;实验题目与说明&#xff09; 利用栈实现数据的分类&#xff0c;将输入的整数以奇偶为标准分别存放到两个栈中&#xff0c;并最终从栈1和栈2输出偶数和奇数序列。 …

如何培养学生的创造性思维

在当下这个时代&#xff0c;创造力的重要性不言而喻。如何在日常教育中潜移默化地培养孩子的创造性思维呢&#xff1f; 一、激发好奇心&#xff0c;让思维自由飞翔 孩子天生就有一颗好奇的心&#xff0c;作为老师&#xff0c;要鼓励他们提问&#xff0c;鼓励他们去探索。好奇…

风车模型与代码

这个模型使用NetLogo乌龟来重复绘制圆圈&#xff0c;定期转动&#xff0c;以便显示出类似万花筒或风车的效果。这是一个演示&#xff0c;展示了一组简单的代理规则如何产生复杂而美丽的图案。 内部工作原理非常简单。创建了许多乌龟&#xff0c;它们的笔都是放下的&#xff08…

电子化学品,预计2025年会增长到4302亿美元

电子化学品市场是一个庞大的细分市场&#xff0c;它包括了广泛的化学品种类&#xff0c;如涂料、塑料、精细化学品、农药和医药等。这个市场的发展相当迅速&#xff0c;下面我们将从全球市场和中国市场两个方面对其发展趋势进行分析。全球市场分析&#xff1a; 从全球市场的角度…

【HBase】——优化

1 RowKey设计 重要&#xff1a;一条数据的唯一标识就是 rowkey&#xff0c;那么这条数据存储于哪个分区&#xff0c;取决于 rowkey 处于 哪个一个预分区的区间内&#xff0c;设计 rowkey的主要目的 &#xff0c;就是让数据均匀的分布于所有的 region 中&#xff0c;在一定程度…

Java重修第二天—学习”方法“

通过学习本篇文章可以掌握如下知识 1、方法的定义 2、方法在计算机中的执行流程。 3、方法使用时常见问题 4、Java中方法的参数传递机制 5、方法重载 1 方法是什么 方法是一种语法结构&#xff0c;它可以把一段代码实现的某种功能封装起来&#xff0c;以便重复利用。 方…