线性DP总结(studying
写在前面
虽然都说线性DP是入门,但我还是今天才开始学
线性DP就是珂以通过线性处理得出答案的一种DP
每一种状态都可以从前面推得,并且推导过程是呈线性的
参考题单(本人现在主要用luogu,所以这些题都是luogu上找的)
下面是例题:
P1057 传球游戏
这道题算是热身题吧
Solution
思路很简单,
每个人手中的球只能从他左边的同学和右边的同学传过来,所以递推求就好了
我们用i表示编号,j表示第几次传球,f[][]表示有几条到达这种状态的“路”
那么可以推出递推式:
f[1][0] = 1;
f[i][j] = f[i-1][j-1] + f[i+1][j-1];
下面是代码:

1 #include<iostream>
2 #include<cstdio>
3 using namespace std;
4 int n, m;
5 int f[33][33];
6 int main()
7 {
8 scanf("%d%d", &n, &m);
9 f[1][0] = 1;
10 for(int j = 1; j <= m; ++j){
11 for(int i = 1; i <= n; ++i){
12 int x, y;
13 if(i - 1 == 0) x = n;
14 else x = i - 1;
15 if(i + 1 == n + 1) y = 1;
16 else y = i + 1;
17 f[i][j] = f[x][j-1] + f[y][j-1];
18 }
19 }
20 printf("%d", f[1][m]);
21
22 return 0;
23 }
P1233 木棍加工
简述题意
如果下次加工的木棍比上一次的又短又细,就不需要准备时间,否则需要一分钟的准备时间
Solution
先将木棍按长度从大到小排序,在跑一个最长上升子序列即可(不知道为什么按宽度排序跑出来90pts
粘代码:

1 #include<iostream>
2 #include<cstdio>
3 #include<algorithm>
4 using namespace std;
5 const int MAXN = 5010;
6 struct Wood{
7 int l,w;
8 bool operator < (const Wood &b) const {return l > b.l;}
9 }wood[MAXN];
10 int n, ans;
11 int f[MAXN];
12 int main()
13 {
14 // freopen("P1233_8.in", "r", stdin);
15 scanf("%d", &n);
16 for(int i = 1; i <= n; ++i){
17 scanf("%d%d", &wood[i].l, &wood[i].w);
18 }
19
20 sort(wood + 1, wood + 1 + n);
21
22 for(int i = 1; i <= n; ++i){
23 f[i] = 1;
24 for(int j = 1; j <= i; ++j){
25 if(wood[i].w > wood[j].w) f[i] = max(f[i], f[j] + 1);
26 }
27 ans = max (ans, f[i]);
28 // cout<<ans<<endl;
29 }
30
31 printf("%d", ans);
32
33 return 0;
34 }
P1020 导弹拦截
简述题意
现有某导弹拦截系统,每一次拦截的导弹只能小于等于上一次拦截的导弹(当然,第一次珂以拦截任意高度的导弹),给你依次飞来的导弹高度,输出最多能拦截的导弹数和拦截所有导弹最少需要多少套系统
Solution
因为这个系统拦截的导弹高度是单调不升的,所以第一问就是一个最长不上升子序列
第二问珂以根据Dilworth定理推得求一个最长上升子序列
某大佬JJPJJ对于求最长上升子序列的证明:
(1)假设打导弹的方法是这样的:取任意一个导弹,从这个导弹开始将能打的导弹全部打完。而这些导弹全部记为为同一组,再在没打下来的导弹中任选一个重复上述步骤,直到打完所有导弹。
(2)假设我们得到了最小划分的K组导弹,从第a(1<=a<=K)组导弹中任取一个导弹,必定可以从a+1组中找到一个导弹的高度比这个导弹高(因为假如找不到,那么它就是比a+1组中任意一个导更高,在打第a组时应该会把a+1组所有导弹一起打下而不是另归为第a+1组),同样从a+1组到a+2组也是如此。那么就可以从前往后在每一组导弹中找一个更高的连起来,连成一条上升子序列,其长度即为K;
(3)设最长上升子序列长度为P,则有K<=P;又因为最长上升子序列中任意两个不在同一组内(否则不满足单调不升),则有
P>=K,所以K=P。
直接暴力

1 /*
2 Work by: Suzt_ilymics
3 Knowledge: 线性DP
4 */
5 #include<iostream>
6 #include<cstdio>
7 using namespace std;
8 const int MAXN = 1e5+4;
9 int n, ans = -1, cnt = -1;
10 int a[MAXN];
11 int f[MAXN], sum[MAXN];
12
13 int max(int x, int y){return x > y ? x : y; }
14
15 int main()
16 {
17 while(cin >> a[++n]);
18 for(int i = 1; i < n; ++i){
19 f[i] = 1;
20 sum[i] = 1;
21 for(int j = 1; j < i; ++j){
22 if(a[j] >= a[i])
23 f[i] = max(f[i], f[j] + 1);
24 if(a[j] < a[i])
25 sum[i] = max(sum[i], sum[j] + 1);
26 }
27 ans = max(ans, f[i]);
28 cnt = max(cnt, sum[i]);
29 }
30
31 printf("%d\n%d", ans, cnt);
32
33 return 0;
34 }
O(n^2)代码
显然会T
所以这里用到了某大佬「已注销」的常数优化方法:
在朴素n^2算法中,用f[i]储存以i结尾的最长不上升子序列长度,如样例
i 1 2 3 4 5 6 7 8
a 389 207 155 300 299 170 158 65
f 1 2 3 2 3 4 5 6
发现当f的值相同时,越后面的导弹高度越高
用d[i]维护f值为i的最后一个导弹的位置,t记录当前已经求出最长不升子序列长度
递推求f时枚举a[d[t]],a[d[t-1]],。。。,a[d[1]]是否≥当前求的导弹高度,是就更新f
这是优化后代码

1 /*
2 Work by: Suzt_ilymics
3 Knowledge: 线性DP, LIS
4 Time: O(??)
5 */
6 #include<iostream>
7 #include<cstdio>
8 using namespace std;
9 const int MAXN = 1e5+4;
10 int n, ans = -1, cnt = -1;
11 int a[MAXN], d[MAXN], t;//用d数组维护f值为i的最后一个导弹的位置
12 int f[MAXN], sum[MAXN];
13
14 int max(int x, int y){return x > y ? x : y; }
15
16 int main()
17 {
18 while(cin >> a[++n]);
19 //第一问:求最长不上升子序列
20 for(int i = 1; i < n; ++i){
21 f[i] = 1;
22 for(int j = ans; j > 0; --j){
23 if(a[i] <= a[d[j]]){
24 f[i] = f[d[j]] + 1; break;
25 }
26 }
27 d[f[i]] = i;
28 ans = max(ans, f[i]);
29 }
30
31 //第二问,求最长上升子序列
32 for(int i = 1; i < n; ++i){
33 sum[i] = 1;
34 for(int j = cnt; j > 0; --j){
35 if(a[i] > a[d[j]]){
36 sum[i] = sum[d[j]] + 1; break;
37 }
38 }
39 d[sum[i]] = i;
40 cnt = max(cnt, sum[i]);
41 }
42
43 printf("%d\n%d", ans, cnt);
44
45 return 0;
46 }
O(??)代码
本人做完这个题突发灵感,写了一道题目这里,希望有大佬能提出具体思路帮我完善题面
线性DP总结(studying的更多相关文章
- LightOJ1044 Palindrome Partitioning(区间DP+线性DP)
问题问的是最少可以把一个字符串分成几段,使每段都是回文串. 一开始想直接区间DP,dp[i][j]表示子串[i,j]的答案,不过字符串长度1000,100W个状态,一个状态从多个状态转移来的,转移的时 ...
- Codeforces 176B (线性DP+字符串)
题目链接: http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=28214 题目大意:源串有如下变形:每次将串切为两半,位置颠倒形成 ...
- hdu1712 线性dp
//Accepted 400 KB 109 ms //dp线性 //dp[i][j]=max(dp[i-1][k]+a[i][j-k]) //在前i门课上花j天得到的最大分数,等于max(在前i-1门 ...
- 动态规划——线性dp
我们在解决一些线性区间上的最优化问题的时候,往往也能够利用到动态规划的思想,这种问题可以叫做线性dp.在这篇文章中,我们将讨论有关线性dp的一些问题. 在有关线性dp问题中,有着几个比较经典而基础的模 ...
- POJ 2479-Maximum sum(线性dp)
Maximum sum Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 33918 Accepted: 10504 Des ...
- poj 1050 To the Max(线性dp)
题目链接:http://poj.org/problem?id=1050 思路分析: 该题目为经典的最大子矩阵和问题,属于线性dp问题:最大子矩阵为最大连续子段和的推广情况,最大连续子段和为一维问题,而 ...
- nyoj44 子串和 线性DP
线性DP经典题. dp[i]表示以i为结尾最大连续和,状态转移方程dp[i] = max (a[i] , dp[i - 1] + a[i]) AC代码: #include<cstdio> ...
- 『最大M子段和 线性DP』
最大M子段和(51nod 1052) Description N个整数组成的序列a[1],a[2],a[3],-,a[n],将这N个数划分为互不相交的M个子段,并且这M个子段的和是最大的.如果M &g ...
- 『最长等差数列 线性DP』
最长等差数列(51nod 1055) Description N个不同的正整数,找出由这些数组成的最长的等差数列. 例如:1 3 5 6 8 9 10 12 13 14 等差子数列包括(仅包括两项的不 ...
随机推荐
- easyui中加载table列表数据 第一次有数据第二次没有数据问题
$('#allUsingProductTable').datagrid({ 加载数据时,第二加载时table会发生变化会出现找不到问题.如果是弹框没有影响,弹框出现出现列表每次都会执行销毁方法. 解 ...
- python-OpenCV 使用GrabCut来实现图片的前景与后景的分割
先上一个效果图: 使用Python3.7+OpenCV 3.x. 需要引入 numpy库. 在图上用鼠标左键和右键标记前景和后景即可.如果需要重新标记图像,关闭程序重新运行. 以下是具体实现代码. # ...
- 一个简单的springboot+mybatis-plus+thymeleaf的学生管理系统
一.登录功能 1.1登录所涉及的功能主要包括拦截器,过滤器,用户在未登录的时候,访问页面会阻止访问的,如图所示: 实现这个功能的主要代码如下所示 1 //拦截器 2 public class Logi ...
- JS中的多层次排序算法
引子 排序在编程中随处可见,从开始学习变成,到项目开发,基本上或多或少会遇到一些排序问题,接下来我要写的是我在实际开发终于到的一个排序问题,一开始卡了我很久,后面随着知识积累,实践变多才解决掉了,不知 ...
- 远程分支删除后,git branch -a还能看到的解决方法
详情https://www.cnblogs.com/wangiqngpei557/p/6058115.html 大家在删除远程分支后 git branch -a 还是可以看到已删除的远程分支,时间一长 ...
- 阿里云centos7[linux]安装nginx
标题 说明 服务器版本 Centos7 x64 nginx版本 1.19.6 作者 walton 一.准备 创建安装包目录并进入 mkdir /usr/dev/nginx cd /usr/dev/ng ...
- Python+MySQL随机试卷及答案生成程序
一.背景 本文章主要是分享如何使用Python从MySQL数据库中面抽取试题,生成的试卷每一份都不一样. 二.准备工作 1.安装Python3 下载地址:https://www.python.org/ ...
- [日常填坑系列]CAP食用指南-版本引用问题
一.前言 最近,由于好久没升级底层框架,一直用着netcore2.2版本,导致有些包没能更新到最新的版本,例如:CAP. 然而,在最近升级到CAP:3.1.2版本的时候,发现有点小坑,只能退回到CAP ...
- Python在项目外更改项目内引用
前言 目前有一个奇葩的需求, 将某个开源项目整合进自己的项目里去调度, 还需要在每次启动这个开源项目时, 加载不同的配置文件进去, 问题是配置文件并不是一个 conf 或者是其他的什么, 而是以 .p ...
- rocketmq-cpp-client Visual Studio 2019 编译
rocketmq-cpp-client Visual Studio 2019 编译 rocketmq-cpp-client 是rocketmq c++版本的 所以我们C++ 开发者使用此项目 构建 获 ...