P3842-DP【黄】
想搜索到最后一层,就必得先完成前面层的搜索任务,这构成了对状态转移的启示,即当前层的DP值应该是此前层转移过来后得到的最佳值。
但这道题看数据范围应该不能用二维数组,抱着侥幸的心理我使用了动态二维数组,dpij表示以第i层第j个为终点时的答案,结果MLE了,喜提42分,详见CODE-1。
后来意识到(其实是瞥了一眼题解后立刻受启发,然后想到的...)从中间节点转移过去是等价于先从边界节点动到中间节点在下去移动的,换句话说不需要存储、记录、判断那么多的状态,只需要存2*n个值就可以,但好像我写假了,不知为什么只有七十多分,详见CODE-2
总结,用记搜思想或者“想搜索到最后一层,就必得先完成前面层的搜索任务”等方法判断出所需的DP的下标的含义,然后在写出状态转移方程,这是我自己归纳的思考DP问题的一种比较简单的思维路径,应该多用用
CODE-1
#include <iostream>
#include <cstring>
#include <string>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <stack>
#include <queue>
#include <map>
#include <unordered_map>
#include <cmath>
//#define int long long
using namespace std;
int * dp[20000+2];
int n,L[20000+2],R[20000+2];
int dfs(int row,int col)
{
if(col<L[row]||col>R[row])return 0;
if(dp[row][col-L[row]]!=-1)return dp[row][col-L[row]];
if(row==1)return dp[row][col-L[row]]=R[row]-1+R[row]-col;
int ANS=99999999;
for(int i=L[row-1];i<=R[row-1];i++)
{
if(i<=R[row]&&i>=L[row])
ANS=min(ANS,dfs(row-1,i)+1+2*(R[row]-max(i,col))+2*(min(i,col)-L[row])+max(i,col)-min(i,col));
else if(i>R[row]) ANS=min(ANS,dfs(row-1,i)+1+i-L[row]+col-L[row]);
else if(i<L[row]) ANS=min(ANS,dfs(row-1,i)+1+R[row]-i+R[row]-col);
}
return dp[row][col-L[row]]=ANS;
}
signed main()
{
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>L[i]>>R[i];
dp[i]=new int[R[i]-L[i]+1];
for(int j=0;j<R[i]-L[i]+1;j++)dp[i][j]=-1;//li~ri->0~ri-li
}
cout<<n-R[n]+dfs(n,R[n])<<endl;
return 0;
}
/*
dfs(n,R[n]);
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
printf("%3d",dfs(i,j));
}
cout<<endl;
}*/
CODE-2
#include <iostream>
#include <cstring>
#include <string>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <stack>
#include <queue>
#include <map>
#include <unordered_map>
#include <cmath>
#define int long long
using namespace std;
int dp[20000+2][3];
int n,L[20000+2],R[20000+2];
int dfs(int row,int col)//now col is left or right
{
if(dp[row][col]!=-1)return dp[row][col];
int ANS=1e16;
if(col==1)//towards L[row]
{
//from L[row-1]
if(L[row-1]<=R[row])
ANS=min(ANS,dfs(row-1,1)+1+R[row]-L[row-1]+R[row]-L[row]);
else
ANS=min(ANS,dfs(row-1,1)+1+L[row-1]-L[row]);
//from R[row-1]
if(R[row-1]<=R[row])
ANS=min(ANS,dfs(row-1,2)+1+R[row]-R[row-1]+R[row]-L[row]);
else
ANS=min(ANS,dfs(row-1,2)+1+R[row-1]-L[row]);
}
else//towards R[row]
{
//from L[row-1]
if(L[row-1]<=L[row])
ANS=min(ANS,dfs(row-1,1)+1+R[row]-L[row-1]);
else
ANS=min(ANS,dfs(row-1,1)+1+L[row-1]-L[row]+R[row]-L[row]);
//from R[row-1]
if(R[row-1]<=L[row])
ANS=min(ANS,dfs(row-1,2)+1+R[row]-R[row-1]);
else
ANS=min(ANS,dfs(row-1,2)+1+R[row-1]-L[row]+R[row]-L[row]);
}
for(int i=L[row-1];i<=R[row-1]/2;i++)
{
if(i<=R[row]&&i>=L[row])
ANS=min(ANS,dfs(row-1,2)+R[row-1]-i+1+2*(R[row]-max(i,col))+2*(min(i,col)-L[row])+max(i,col)-min(i,col));
else if(i>R[row]) ANS=min(ANS,dfs(row-1,2)+1+i-L[row]+col-L[row]);
else if(i<L[row]) ANS=min(ANS,dfs(row-1,2)+1+R[row]-i+R[row]-col);
}
return dp[row][col]=ANS;
}
signed main()
{
scanf("%ld",&n);
for(int i=1;i<=n;i++)
{
scanf("%ld%ld",&L[i],&R[i]);
for(int j=0;j<3;j++)dp[i][j]=-1;//li~ri->0~ri-li
}
dp[1][1]=R[1]-1+R[1]-L[1];
dp[1][2]=R[1]-1;
cout<<min(n-R[n]+dfs(n,2),n-L[n]+dfs(n,1))<<endl;
return 0;
}
/*
dfs(n,R[n]);
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
printf("%3d",dfs(i,j));
}
cout<<endl;
}*/
P3842-DP【黄】的更多相关文章
- 【洛谷 P3842】[TJOI2007]线段(DP)
裸DP.感觉楼下的好复杂,我来补充一个易懂的题解. f[i][0]表示走完第i行且停在第i行的左端点最少用的步数 f[i][1]同理,停在右端点的最少步数. 那么转移就很简单了,走完当前行且停到左端点 ...
- DP擎天
DP! 黄题: 洛谷P2101 命运石之门的选择 假装是DP(分治 + ST表) CF 982C Cut 'em all! 树形贪心 洛谷P1020 导弹拦截 单调队列水题 绿题: 洛谷P1594 护 ...
- BestCoder Round #89 02单调队列优化dp
1.BestCoder Round #89 2.总结:4个题,只能做A.B,全都靠hack上分.. 01 HDU 5944 水 1.题意:一个字符串,求有多少组字符y,r,x的下标能组成等比数列 ...
- FZU 1025 状压dp 摆砖块
云峰菌曾经提到过的黄老师过去讲课时的摆砖块 那时百度了一下题目 想了想并没有想好怎么dp 就扔了 这两天想补动态规划知识 就去FZU做专题 然后又碰到了 就认真的想并且去做了 dp思想都在代码注释里 ...
- 合并傻子//区间dp
P1062 合并傻子 时间: 1000ms / 空间: 131072KiB / Java类名: Main 背景 从前有一堆傻子,钟某人要合并他们~但是,合并傻子是要掉RP的...... 描述 在一个园 ...
- [BZOJ 2165] 大楼 【DP + 倍增 + 二进制】
题目链接:BZOJ - 2165 题目分析: 这道题我读了题之后就想不出来怎么做,题解也找不到,于是就请教了黄学长,黄学长立刻秒掉了这道题,然后我再看他的题解才写出来..Orz 使用 DP + 倍增 ...
- codeforces284 div1 B:概率dp
蛋疼的期末..好久没有A题了,,惭愧啊 昨晚打起精神准备做cf 结果竟然忘记注册了..拿学长号看了看题,今早起来补了一道dp 题目大意: 有n首歌,你需要边听边猜 对于第 i 首歌 每听一分钟你猜出它 ...
- 2017广东工业大学程序设计竞赛初赛 题解&源码(A,水 B,数学 C,二分 D,枚举 E,dp F,思维题 G,字符串处理 H,枚举)
Problem A: An easy problem Description Peter Manson owned a small house in an obscure street. It was ...
- BZOJ 2595: [Wc2008]游览计划 [DP 状压 斯坦纳树 spfa]【学习笔记】
传送门 题意:略 论文 <SPFA算法的优化及应用> http://www.cnblogs.com/lazycal/p/bzoj-2595.html 本题的核心就是求斯坦纳树: Stein ...
- BZOJ 1004: [HNOI2008]Cards [Polya 生成函数DP]
传送门 题意:三种颜色,规定使用每种颜色次数$r,g,b$,给出一个置换群,求多少种不等价着色 $m \le 60,\ r,g,b \le 20$ 咦,规定次数? <组合数学>上不是有生成 ...
随机推荐
- c++学习,和友元函数
第一友元函数访问私有元素时不会显示,但是是可以调用的(我使用的是gcc10.3版本的)友元函数可以访问任何元素.就是语法你别写错了. 继承如果父类已经写了构造函数,子类一定要赋值给构造函数,要么父类就 ...
- 【scikit-learn基础】--『监督学习』之 岭回归
岭回归(Ridge Regression)是一种用于处理共线性数据的线性回归改进方法.和上一篇用基于最小二乘法的线性回归相比,它通过放弃最小二乘的无偏性,以损失部分信息.降低精度为代价来获得更实际和可 ...
- 2023总结与展望--Empirefree
今年一篇博客都没写过了,好像完全在忙在工作和生活上面了,珍惜自我,保持热情,2024对我好点 目录 1. 年终总结 1.1.学习工作计划 1.2. 生活计划 1.3 个人总结 2. 未来展望 1. 年 ...
- cache操作:clean、invalidate与flush的含义
前言 本文试图搞清楚cache几个操作:clean.invalidate与flush的含义.由于只用过ARM和RISC-V,所以是从ARM和RISC-V的角度来说明. cache line cache ...
- 从零玩转系列之微信支付实战PC端支付微信退款接口搭建 | 技术创作特训营第一期
一.前言 从零玩转系列之微信支付实战PC端支付微信退款接口搭建 | 技术创作特训营第一期 继前文章取消订单接口和查询订单接口此篇为申请退款流程,此篇文章过长我将分几个阶段的文章发布(项目源码都有,小程 ...
- 【2】从零玩转OSS阿里云存储服务之Java代码操作-2-cong-ling-wan-zhuan-oss-a-li-yun-cun-chu-fu-wu-zhi-java-dai-ma-cao-zuo
title: [2]从零玩转OSS阿里云存储服务之Java代码操作 date: 2021-06-09 17:37:14.486 updated: 2021-12-26 17:43:12.779 url ...
- 在centos7.9中 修改docker0 的网卡默认IP地址
docker0网卡的默认IP地址为172.17.0.1/16 因此很可能会与企业网中的业务地址冲突,为了解决这个问题,必须修改docker0的网卡配置,操作如下 1.查看网卡docker0的默认地址 ...
- Python——第一章:if语法规则
if语句的语法规则: ======第一种====== if 条件: 代码 如果条件成立就执行代码 如果不成立, 就不执行 案例1: mo ...
- Visual Studio 2022 Preview设置简体中文
前言: 作为尝鲜小分队队长,对于vs的升级版Visual Studio 2022 Preview肯定也开始用上了,不过之前一直以为还没有出中文的语言包所以一直用的是英文版的,搞得英文本来不好的我很是不 ...
- vue点击图片获取图片原像素坐标
<template> <div> <img ref="image" width="1500px" :src="image ...