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$ 咦,规定次数? <组合数学>上不是有生成 ...
随机推荐
- [ABC262B] Triangle (Easier)
Problem Statement You are given a simple undirected graph with $N$ vertices and $M$ edges. The verti ...
- 目标检测工具安装使用--labelImg
如果想要在深度学习中训练我们自己的模型,就得对图片进行标注.labelImg是一个超级方便的目标检测图片标注工具,打开图片后,只需用鼠标框出图片中的目标,并选择该目标的类别,便可以自动生成voc格式的 ...
- Kernel Memory 入门系列:Kernel Memory Service
Kernel Memory 入门系列:Kernel Memory Service 在 Kernel Memory 的 GitHub 仓库中有一个单独的项目 Service , 用于提供独立的Kerne ...
- 算法2:Hanoi塔
汉诺(Hanoi)塔 一.背景介绍 在印度,有这么一个古老的传说:在世界中心贝拿勒斯(在印度北部)的圣庙里,一块黄铜板上插着三根宝石针.印度教的主神梵天在创造世界的时候,在其中一根针上从下到上地穿好了 ...
- Web测试基本思路:UI测试、功能测试和兼容性测试
关于网站测试的基本思路,希望对测试小白有所帮助. 一.UI测试 用户界面测试主要是拿待测网页和设计稿进行对比,主要主要以下4点: 1.注重细节: 这点最基本,就是对比是细心.细心再细心. 2.主要整体 ...
- libGDX游戏开发之Box2D碰撞(十五)
libGDX游戏开发之Box2D(十四) libGDX系列,游戏开发有unity3D巴拉巴拉的,为啥还用java开发?因为我是Java程序员emm-国内用libgdx比较少,多数情况需要去官网和goo ...
- Java数组常见的几种排序。
public class code2 { public static void main(String[] args) { int[] x = {37, 89, 23}; for (int z = 0 ...
- 21、Scaffold属性 FloatingActionButton实现类似闲鱼App底 部导航凸起按钮
FloatingActionButton详解 FloatingActionButton简称FAB ,可以实现浮动按钮,也可以实现类似闲鱼app的底部凸起导航 实现类似闲鱼App底部导航凸起按钮 c ...
- 共探AI大模型时代下的挑战与机遇,华为云HCDE与大模型专家面对面
摘要:近日,华为开发者大会2023(cloud)"开发者生态创新发展圆桌会议"在东莞华为溪流背坡村成功举办. 2023年7月8日,华为开发者大会2023(cloud)"开 ...
- 华为云PB级数据库GaussDB(for Redis)揭秘第五期:高斯 Redis 在IM场景中的应用
摘要:揭秘高斯 Redis 在IM场景中的应用. 本文分享自华为云社区<华为云PB级数据库GaussDB(for Redis)揭秘第五期:高斯 Redis 在IM场景中的应用>,原文作者: ...