DP-DAY3游记
问题 A: 2017夏令营第一阶段(Day3)问题A拆分数字I
题目描述
例如:N=4,有1+1+1+1、1+1+2、1+2+1、1+3、2+1+1、2+2、3+1、4八种方法。
输入
输出
样例输入
3
样例输出
4
第一题是一道典型的找子问题的题目,设f[i]表示N=i情况下的方案数,我们拿题目中N=4的情况讲述。
我们可以把他得到的答案(1+1+1+1、1+1+2、1+2+1、1+3、2+1+1、2+2、3+1、4)这堆东西分一下类别。
以1开头的有:1+1+1+1,1+1+2,1+2+1,1+3
以2开头的有:2+1+1,2+2,
以3开头的有:3+1
以4开头的有:4
我们不难发现,(以1开头为例),实际上就是f[3],因为开头1后面的数字的总和恰好为3,所以方案数自然为f[3]
以此类推,以2开头的方案数为f[2],以3开头的方案数为f[1],以4开头的为......
所以f[4]=f[3]+f[2]+f[1],那么f[3]=f[2]+f[1],我们发现,其实f[4]=2*f[3],所以以此类推f[3]=2*f[2]
我们以此找到规律f[n]=f[n-1]*2,(妙啊~
f[0]要初始化为1,qwq
来,上代码
1 #include<bits/stdc++.h>
2 using namespace std;
3 long long n,ans; //看着数据大小,无奈地打起了long long(qwq
4 int main(){
5 scanf("%lld",&n);
6 ans=pow(2,n-1); //运用f[n]=f[n-1]*2的规律
7 printf("%lld",ans);
8 return 0;
9 }
完美!
问题 B: 2017夏令营第一阶段(Day3)问题B方格最短路径
题目描述
输入
下面n行,每行m个整数,每个数范围在[1, 100] 。
输出
样例输入
3 4
3 2 3 7
2 1 5 1
3 2 1 6
样例输出
15
这一道题也是一道经典子问题的题目。
这道题要求的值是从左上角到达右下角点(每到达一个点加上那个点的值)的值最小值。
设这道题的f[i][j]表示到点(i,j)时得到的最优值,那么我们最终要求的目标就是f[n][m]。
题目中要求只能走右边和下边,所以点f[n][m]只能从f[n-1][m]和f[n][m-1]两个点过来因此此时我们需要求出f[n-1][m]和f[n][m-1]两个点的最优值,以此内推,我们首先要求的是f[1][1]的最优值,然后往别的点便利最优值,从而得出状态转移方程,f[i][j]=min(f[i-1][j],f[i][j-1])+a[i][j]
妙啊~
上代码!
1 #include<bits/stdc++.h>
2 using namespace std;
3 int n,m;
4 int a[1005][1005];
5 int f[1005][1005];
6 const int oo=0x7f7f7f; //最大值
7 int main(){
8 scanf("%d%d",&n,&m);
9 for(int i=1;i<=n;i++)
10 for(int j=1;j<=m;j++)
11 scanf("%d",&a[i][j]);
12 for(int i=0;i<=n+1;i++)
13 for(int j=0;j<=m+1;j++)
14 f[i][j]=oo; //这里需要初始化一下
15 f[0][1]=f[1][0]=0;
16 for(int i=1;i<=n;i++)
17 for(int j=1;j<=m;j++){
18 f[i][j]=min(f[i][j-1],f[i-1][j])+a[i][j];
19 }
20 printf("%d",f[n][m]);
21 return 0;
22 }
完美!
问题 C: 2017夏令营第一阶段(Day3)问题C最长上升序列
题目描述
输入
第二行有N个整数,每个数范围在[1, 1000000] 。
输出
样例输入
8
9 1 3 7 4 1 5 5
样例输出
4
如果去过洛古的大佬,应该知道有一道题叫做导弹拦截,那道题跟这道题及其相似。
这道题设f[i]为当找到第i个数字时的最优值。
那么我们可以枚举前面i前面的数值然后如果找到是满足递增情况的时候就可以加多一种情况,因此方程就是if(a[j]>a[i])f[i]=max(f[i],f[j]+1);
上代码!
1 #include<bits/stdc++.h>
2 using namespace std;
3 int n,f[10005];
4 int a[10005];
5 const int oo=0x7f7f7f;
6 int mmax;
7 int main(){
8 scanf("%d",&n);
9 a[0]=-oo;
10 for(int i=1;i<=n;i++)scanf("%d",&a[i]);
11 for(int i=n;i>=1;i--){
12 f[i]=1;
13 for(int j=i+1;j<=n;j++)
14 if(a[j]>a[i])f[i]=max(f[i],f[j]+1);
15 mmax=max(f[i],mmax); //统计最优值
16 }
17 printf("%d",mmax);
18 return 0;
19 }
完美!
问题 D: 2017夏令营第一阶段(Day3)问题D拆分数字II
题目描述
把数字N拆分一些正整数的和,问有多少种本质不同的方法?
例如:N=4,有1+1+1+1、1+1+2、1+3、2+2、4五种方法。
提示:1+3和3+1是本质相同的方法。
输入
第一行:一个整数N,范围在[1,50]。
输出
输出方案数。
样例输入
3
样例输出
3
从题面分析本题与第一题类似但又不同,因为以数学的思想讲第一题是排列,而本题为组合。
我们不妨把他想象成完全背包。
以题目中的例子“N=4,有1+1+1+1、1+1+2、1+3、2+2、4”,我把得到组合的第一个数字称为num[i][1](num[1][1]=1,num[1][2]=1,num[1][3]=1,num[1][4]=1……num[4][1]=4)
那么num[i][j]可以放1~N的数字,然后按照完全背包的过程就是每个数字(1~N)你可以取无限次,只要满足num[i][1]+num[i][u]总和为N就行了。
所以我们可以用完全背包的思路解决这道题。
上代码~!
1 #include<bits/stdc++.h>
2 using namespace std;
3 long long n,f[10005];
4 int main(){
5 scanf("%lld",&n);
6 f[0]=1; //千万别少了初始化
7 for(long long i=1;i<=n;i++) //完全背包
8 for(long long j=i;j<=n;j++)
9 f[j]+=f[j-i];
10 printf("%lld",f[n]);
11 return 0;
12 }
完美!
问题 E: 2017夏令营第一阶段(Day3)问题E :砖块(brick)
题目描述
现有一种形状为1*2的砖块,要用这种砖块摆成宽为2,长为n的墙,问有多少种方案?
输入
该题有若干组测试数据,每组数据一行,一行一个正整数n(n<=1000000)表示长,当n=0时结束。
输出
对应每组的方案数(模1000000007)。
样例输入
1
2
3
0
样例输出
1
2
3
提示

这道题跟一道叫做“台阶问题”的题目很相似。(也就是说你可以双倍经验
我们不妨把1*2的方块竖着放定义为走1步,而横着放定义为走2步。
那么问题就被我们转换成一个新问题:一个n阶的台阶,你可以走1步或者走2步,最后一步必须走到终点,问有多少种走法。
(然而台阶问题可以走1~K步,也就是说这道题比台阶问题还简单。
我们设f[i]为走到第i个位置的时候的方案总数,那么我们想要求的答案就是f[n]。
那么我们怎么得到f[n]呢?显然可以走1步或者2步,我们就可以从f[n-1]和f[n-2]两个格子过来。
又因为加法原理,我们得到公式:f[n]=f[n-1]+f[n-2],以此类推,f[i]=f[i-1]+f[i-2]。
这不就是著名的肥波纳妾数列吗,呸(斐波那契数列【手动滑稽】
好了不多说,上代码!
1 #include<bits/stdc++.h>
2 using namespace std;
3 long long n=1,k,a[1000005];
4 const long long mod=1000000007; //别忘了mod
5 int main(){
6 while(n!=0){
7 memset(a,0,sizeof(a));
8 scanf("%lld",&n);
9 if(n==0)return 0;
10 a[0]=1;
11 for(long long i=1;i<=n;i++)
12 a[i]=a[i-1]+a[i-2],a[i]%=mod; //肥波纳妾啦(
13 printf("%lld\n",a[n]);
14 }
15 return 0;
16 }
完美~!
问题 F: 2017夏令营第一阶段(Day3)问题F :合唱队形
题目描述
N位同学站成一排,音乐老师要请其中的(N-K)位同学出列,使得剩下的K位同学排成合唱队形。
合唱队形是指这样的一种队形:设K位同学从左到右依次编号为1,2…,K,他们的身高分别为T1,T2,…,TK, 则他们的身高满足T1 < …Ti+1 > … > TK(1 <= i <= K)。
你的任务是,已知所有N位同学的身高,计算最少需要几位同学出列,可以使得剩下的同学排成合唱队形。
输入
第一行是一个整数N(2 <= N <= 200),表示同学的总数。
第二行有n个整数,用空格分隔,第i个整数Ti(130 <= Ti <= 230)是第i位同学的身高(厘米)。
输出
包括一行,这一行只包含一个整数,就是最少需要几位同学出列。
样例输入
8
186 186 150 200 160 130 197 220
样例输出
4
其实这道题我什么也不想说,其实就是第三题的升级版,你只需要两边都dp一遍就好了,上代码~!(没看懂得朋友可以去琢磨第三题
1 #include<bits/stdc++.h>
2 using namespace std;
3 int n,a[10005],ans,zans[10005],zans1[10005];
4 int main(){
5 scanf("%d",&n);
6 for(int i=1;i<=n;i++)scanf("%d",&a[i]);
7 for(int i=1;i<=n;i++)
8 for(int j=1;j<=i;j++)
9 if(a[i]>a[j])zans[i]=max(zans[i],zans[j]+1); //像第三题一样dp一遍左边(从左往右
10 for(int i=n;i>=1;i--)
11 for(int j=n;j>=i;j--)
12 if(a[i]>a[j])zans1[i]=max(zans1[i],zans1[j]+1); //像第三题一样dp一遍右边(从右往左
13 for(int i=1;i<=n;i++)
14 ans=max(ans,zans[i]+zans1[i]+1); //相加便利得结果
15 printf("%d\n",n-ans); //剩下的就是需要移除的人的个数
16 return 0;
17 }
问题 G: 2017夏令营第一阶段(Day3)问题G :维修栅栏(fence)
题目描述
农场的栅栏年久失修,出现了多处破损,晶晶准备维修它,栅栏是由n块木板组成的,每块木板可能已经损坏也可能没有损坏。晶晶知道,维修连续m个木板(这m个木板不一定都是损坏的)的费用是sqrt(m)。可是,怎样设计方案才能使总费用最低呢?请你也来帮帮忙
输入
第一行包含一个整数n(n≤2500),表示栅栏的长度;
第二行包含n个由空格分开的整数。如果第i个数字是0,则表示第i块木板已经损坏,否则表示没有损坏。
输出
仅包含一个实数,表示最小维修费用;注意:答案是小数,最少精确到0.001。
样例输入
9
0 –1 0 1 2 3 0 –2 0
样例输出
3.000
这一道题非常经典,相对于前几道题有点难度,嗯。
首先来理解一下题目,有些朋友会想欸,我一个个修他不香吗,为什么那么麻烦。
如果你这样理解你就错了,我们手动水一组样例:“0,1,0”
那么如果我们一个个修我们就要花费√(1)+√(1)=2的费用
但是你有没有想过√(3)=1.732050807568877……,而且<√(1)+√(1)
所以这就是我们要研究的问题。
我们设f[i]为修到第i个围栏时得到的最小费用。
那么我们要求得自然就是f[n]。
那么f[n]怎么求呢?
我们假设第i个是数字“0”。
那么f[i]现在面临得问题就是单个修还是连着修,那么我们不妨把这些结果一一算出来比较大小。
我们用一个j去枚举连续修j个栅栏时候得情况那么我们如果连续修得话,结果自然就是f[i-j]+sqrt(j),所以我们只需要比较这些f[i-j]+sqrt(j)找到最小得一个,他就是f[i]得值。
从而得到方程:f[i]=min(f[i],f[i-j]+sqrt(j));
上代码!
1 #include<bits/stdc++.h>
2 using namespace std;
3 int n;
4 double f[10005];
5 int wall[100005];
6 const int oo=0x7f7f7f;
7 int main(){
8 scanf("%d",&n);
9 for(int i=1;i<=n;i++)scanf("%d",&wall[i]);
10 for(int i=1;i<=n;i++){
11 if(!wall[i]){ //判断如果到达一个需要修得点得时候就判断怎么修这个点
12 f[i]=oo;
13 for(int j=1;j<=i;j++){ //枚举修j个栅栏得情况
14 f[i]=min(f[i],f[i-j]+sqrt(j)); //状态转移方程
15 }
16 }
17 else f[i]=f[i-1]; //如果不需要修那么就继承上一代得意志(此时得到的最优值就是上一个的值
18 }
19 printf("%.3f",f[n]); //别忘了3位小数
20 return 0;
21 }
DP-DAY3游记的更多相关文章
- 清北学堂dp图论营游记day3
.状态压缩dp: 对于这个我们引入二进制状态压缩,因为任何一个数都可以二进制表示,而其二进制表示上每一位都可以表示当前位置是否有元素,这就构成了状态压缩. 对于这个题,上下行&一下就行. 状压 ...
- CCPC-Wannafly Winter Camp Day3 Div1 - 精简改良 - [生成树][状压DP]
题目链接:https://zhixincode.com/contest/14/problem/D?problem_id=206 样例输入 1 5 5 1 2 1 1 3 1 2 4 1 2 5 1 ...
- 【CCPC-Wannafly Winter Camp Day3 (Div1) D】精简改良(状压DP)
点此看题面 大致题意: 给你一张图,定义\(dis(i,j)\)为\(i\)与\(j\)的最短距离,现要求删去若干条边,使得图仍然联通,且\(\sum_{i=1}^n\sum_{j=i+1}^ndis ...
- 帝都Day3——各种dp
备注:Day1 Day2记得笔记太233,所以就不发了 备注2:Day4~Day7发不发看心情qaq (7.17持续更新中...) 动态规划A 记忆化搜索 & 动态规划初步 8点15: 杨姓d ...
- 牛客国庆集训派对Day3 B Tree(树形dp + 组合计数)
传送门:https://www.nowcoder.com/acm/contest/203/B 思路及参考:https://blog.csdn.net/u013534123/article/detail ...
- 清北学堂dp图论营游记day2
上午讲数位dp和背包问题. 先讲背包: 完全背包:换了个顺序: 多重背包: 多重背包优化: 这样把每个物品分成这些组,那么把他们转变成不同的物品,就变成了01背包问题: 滑动窗口取最值问题.单调队列优 ...
- 清北学堂dp图论营游记day1
讲课人: 老师对dp的理解是类似于分治思想,由小状态推出大状态.不同的是分治算法没有重叠子问题. dp把子问题越划越小,从而推出了基础状态.然后是dp方程,要满足简洁性,并且充分描述能够影响最后结果的 ...
- 清北学堂dp图论营游记day6
xysq主讲: 求点双和边双代码: 对所有点进行染色,如果存在一种方案使得相邻的点不同色,那么他就是个二分图. 二分图两种求法,1,dfs求增广路. 2,网络流:最大流=最小割 差分约束: 下午又要考 ...
- 清北学堂dp图论营游记day5
ysq主讲: tarjan缩点+拓扑+dij最短路. floyd..... 单源..最长路... 建正反两个图. 二分答案,把大于答案的边加入到新图中,如果能走过去到终点,就可以. 或者:从大到小加边 ...
- 清北学堂dp图论营游记day4
依然zhx讲. 讲了概率与期望: 期望:事件结果的平均大小.记作E(x). E(x)=每种结果的大小与其概率的乘积的和. 例如,记掷一枚骰子的点数为x E(x)=1*(1/6)+2*(1/6)+3*( ...
随机推荐
- ABBYY FineReader 与尚书七号OCR的对比
ABBYY FineReader 与尚书七号OCR都是帮助我们识别文字的工具,使用的都是OCR技术,如今文字识别工具是我们学习和工作经常会使用的,它们的功能是否实用和好用?现在通过对比的方式来探讨. ...
- Boom 3D的保真度是什么,如何应用
Boom 3D是一款非常优秀的3D音频软件,拥有3D音效.环境模式.空间模式.夜间模式.保真度等多种音效模式,可以为用户提供多种音效体验感. 第一.什么是保真度 或许第一次接触音频软件的朋友就会问到什 ...
- vulnhub: DC 4
信息收集: yurang@kali:~$ nmap -sn 192.168.76.1/24 Starting Nmap 7.80 ( https://nmap.org ) at 2020-08-04 ...
- Httprunner初步学习
一:简介 一直在技术博客上看到Httprunner测试框架,但始终不太明白这个框架的具体作用,今天就花点时间来初步学习了解一下. HttpRunner 是一款面向 HTTP(S) 协议的通用测试框架, ...
- python搭建本地共享文件服务器
1.安装python 去官网下载python最新版,然后安装配置好环境 2.运行命令 在终端上输入以下命令 python3 -m http.server 当你执行完这个命令的时候,你的电脑会监听 80 ...
- Istio 之ServiceEntry
使用服务条目资源(ServiceEntry)可以将条目添加到 Istio 内部维护的服务注册表中.添加服务条目后,Envoy 代理可以将流量发送到该服务,就好像该服务条目是网格中的服务一样.通过配置服 ...
- Jmeter-BeanShell断言的运用一(JSON响应数据与数据库比对)
前言 最近在学习BeanShell断言,发现有点强大哈,只要会写代码,就没有什么是断言不了的,哈哈哈,不过我现在只会写点蹩脚的代码,下面将介绍下如何将返回的JSON数据与数据库数据做对比. 注:本次涉 ...
- 关于transition动画效果中,滚动条会闪一下就消失的问题
具体问题说明: 我在通过transition来改变width的长度,在transition变化过程中,底下的滚动条会闪烁一下. 问题原理:因为是里面容器没办法完全被装下,并且容器的宽度被限制住了. 解 ...
- Linux之【安装系统后的调优和安全设置】
关闭SElinux功能 •修改配置文件使其永远生效 第一种修改方法vi vi /etc/sysconfig/selinuc 或者 vi /etc/selinux/config修改: SELINUX=d ...
- 第三十六章、PyQt输入部件:QAbstractSpinBox派生类QSpinBox、 QDoubleSpinBox、QDateTimeEdit、QDateEdit和QTimeEdit
专栏:Python基础教程目录 专栏:使用PyQt开发图形界面Python应用 专栏:PyQt入门学习 老猿Python博文目录 老猿学5G博文目录 一.概述 Designer输入部件中的Spin B ...