题意:中文 https://vjudge.net/problem/POJ-1661

题解:设两个dp数组,dpl[i]存 从第i块板左边到地上所花的最短时间,dpr[i]存右边的。

    将所有板按高度排序 ,从地面到人分别编号为0,1~n, n+1

坑:dp方程写错了个字母。

  一开始只用了一个dp数组(还改半天)

  没考虑同一高度

  人与地板算入dp数组时的赋值

#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<vector>
#include<cstring>
#include<set>
#include<algorithm>
#include<stack>
#include<string>
#include<cstdio>
#define _for(i, a, b) for (int i = (a); i<(b); ++i)
using namespace std;
const int N = 1e3 + ; struct plat {
int l, r, h;
}p[N];
int dpl[N],dpr[N];//从第e块plat边缘一直掉到地上所需的最短时间
bool cmp(plat a, plat b) {
return a.h < b.h;
}
int find(int x,int now) {
if (now == ) return ;
else for (int i = now-; i >=; i--) {
if (p[i].h == p[now].h)continue;//改:同高度//其实不用考虑
if (p[i].l <= x&&p[i].r >= x) return i;
}
return ;//直接掉到地上
}
//大改:算法错误。
int main()
{
int t;
cin >> t;
while (t--) {
_for(i, , N) dpl[i]=dpr[i] = 1e9;
int n, x, y, mn;
cin >> n >> x >> y >> mn;
_for(i, , n+) {cin >>p[i].l>>p[i].r>>p[i].h;}
p[n+].l = p[n+].r = x; p[n+].h = y;
p[].l = -2e6; p[].r = 2e6; p[].h = ; //改:考虑掉到地上,不能这样改。
sort(p, p + n+,cmp);
//查找落到下面的那一块:可以排序后二分
_for(i, , n+) {
int idl= find(p[i].l,i), idr= find(p[i].r,i);
if (idl == ) { if (p[i].h <= mn) dpl[i] = p[i].h; }
else if (p[i].h - p[idl].h <= mn)
        { dpl[i] = min(dpl[i], dpl[idl] + p[i].h - p[idl].h + p[i].l - p[idl].l);
        dpl[i] = min(dpl[i], dpr[idl] + p[i].h - p[idl].h - p[i].l + p[idl].r);}
if (idr == ) { if (p[i].h <= mn) dpr[i] = p[i].h; }
else if (p[i].h - p[idr].h <= mn)
{ dpr[i] = min(dpr[i], dpl[idr] + p[i].h - p[idr].h + p[i].r - p[idr].l);
dpr[i] = min(dpr[i], dpr[idr] + p[i].h - p[idr].h - p[i].r + p[idr].r); } }
int i = n + ;
int idl = find(p[i].l, i);
if (idl == ) { if (p[i].h - p[idl].h <= mn) dpl[i] = p[i].h - p[idl].h; }
else if (p[i].h - p[idl].h <= mn)
{ dpl[i] = min(dpl[i], dpl[idl] + p[i].h - p[idl].h + p[i].l - p[idl].l);
dpl[i] = min(dpl[i], dpr[idl] + p[i].h - p[idl].h - p[i].l + p[idl].r); }
cout << dpl[n+]<<endl;
} system("pause");
}

附记忆递归代码:

#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<vector>
#include<cstring>
#include<set>
#include<algorithm>
#include<stack>
#include<string>
#include<cstdio>
#define _for(i, a, b) for (int i = (a); i<(b); ++i)
using namespace std;
const int N = 1e3 + ;
const int INF = 1e6;
struct plat {
int l, r, h;
bool operator<(const plat &p2)const { return h > p2.h; }
}p[N];
int dpl[N],dpr[N],L[N];//从第e块plat边缘一直掉到地上所需的最短时间
bool cmp(plat a, plat b) {
return a.h < b.h;
}
int find(int x,int now) {
if (now == ) return ;
else for (int i = now-; i >=; i--) {
if (p[i].h == p[now].h)continue;//改:同高度
if (p[i].l <= x&&p[i].r >= x) return i;
}
return ;//直接掉到地上
}
int n, x, y, mn;
int dpfun(int l, bool bleft) {
int y = p[l].h, x;
x = bleft ? p[l].l : p[l].r;
int i;
for ( i = l+; i <= n; i++) if (p[i].l <= x&&p[i].r >= x) { break; } if (i <= n) { if (y - p[i].h >mn) return INF; }else {if(y>mn)return INF;else return y;}
int nl = y - p[i].h + x - p[i].l;
int nr = y - p[i].h + p[i].r - x;
if (dpl[i] == -)dpl[i] = dpfun(i, true);
if (L[i] == -)L[i] = dpfun(i, false);
nl += dpl[i];
nr += L[i];
if (nl < nr)return nl; return nr; }
//大改:算法错误。
int main()
{
int t;
cin >> t;
while (t--) {
_for(i, , N) dpl[i] = dpr[i] =L[i]= -; cin >> n >> x >> y >> mn;
_for(i, , n + ) { cin >> p[i].l >> p[i].r >> p[i].h; } p[].l = x; p[].r = x; p[].h = y; //改:考虑掉到地上,不能这样改。
sort(p, p + n + );
//查找落到下面的那一块:可以排序后二分
cout << dpfun(, true) << endl;
}
system("pause");
}

Help Jimmy POJ - 1661 数字三角DP的更多相关文章

  1. E - Help Jimmy POJ - 1661 dp

    E - Help Jimmy POJ - 1661 这个题目本身不是很难,但是可以更加优化这个写法. 开始是n*n #include <cstdio> #include <cstri ...

  2. Help Jimmy POJ - 1661 dp

    #include<iostream> #include<stdio.h> #include<algorithm> #include<cstring> u ...

  3. POJ 1661 Help Jimmy(递推DP)

    思路: 1. 每个板子有左右两端, dp[i][0], dp[i][1] 分别记录左右端到地面的时间 2. 从下到上递推计算, 上一层的板子必然会落到下面的某一层板子上, 或者地面上 总结: 1. 计 ...

  4. POJ 1661 Help Jimmy(C)动态规划

    没刷过 POJ,这题是论坛有人问的,我才看看. 我发现 POJ 注册很奇怪,账号总是登不上去,弄的我还注册两个.Emmm 首次体验很差,还好我不在 POJ 刷题. 题目链接:POJ 1661 Help ...

  5. DP问题练习1:数字三角最短路径问题

    DP问题练习1:数字三角最短路径问题 问题描述 给定一个数字三角形,找到从顶部到底部的最小路径和.每一步可以移动到下面一行的相邻数字上. 样例: 比如,给出下列数字三角形: 2 3 4 6 5 7 4 ...

  6. POJ.3624 Charm Bracelet(DP 01背包)

    POJ.3624 Charm Bracelet(DP 01背包) 题意分析 裸01背包 代码总览 #include <iostream> #include <cstdio> # ...

  7. 取数字(dp优化)

    取数字(dp优化) 给定n个整数\(a_i\),你需要从中选取若干个数,使得它们的和是m的倍数.问有多少种方案.有多个询问,每次询问一个的m对应的答案. \(1\le n\le 200000,1\le ...

  8. 繁繁的数字 背包DP

    繁繁的数字 背包DP 问一个数\(n\)有多少种二进制分解方案数 \(n\le 10^5\) 如7有7=4+2+1=4+1+1+1=2+2+2+1=2+2+1+1+1=2+1+1+1+1+1=1+1+ ...

  9. POJ 2995 Brackets 区间DP

    POJ 2995 Brackets 区间DP 题意 大意:给你一个字符串,询问这个字符串满足要求的有多少,()和[]都是一个匹配.需要注意的是这里的匹配规则. 解题思路 区间DP,开始自己没想到是区间 ...

随机推荐

  1. Java显示指定类型的文件

    文件作为存储数据的单元,会根据数据类型产生很多分类,也就是所谓的文件类型.在对数据文件进行操作时,常常需要根据不同的文件类型来作不同的处理.本实例实现的是读取文件夹指定类型的文件并显示到表格控件中.这 ...

  2. 8 -- 深入使用Spring -- 3...4 在ApplicationContext中使用资源

    8.3.4 在ApplicationContext中使用资源 不管以怎样的方式创建ApplicationContext实例,都需要为ApplicationContext指定配置文件,Spring允许使 ...

  3. backbone学习笔记:视图(View)

    Backbone 视图对象主要用来渲染数据,监听事件. Backbone的视图对象可以展示Model数据,也可以把用户编辑的Model数据传递到后台,可以通过监听事件操作视图里的DOM元素 举例: v ...

  4. Android中显示照片的Exif信息

    package com.hyzhou.pngexifdemo; import android.media.ExifInterface; import android.os.Bundle; import ...

  5. 【RF库Collections测试】Reverse List

    Name:Reverse ListSource:Collections <test library>Arguments:[ list_ ]Reverses the given list i ...

  6. jQuery ajax中serialize()方法增加其他参数

    表单提交 使用jQuery.ajax()进行表单提交时,需要传递参数,最直接的方法便是使用Form的serializa()将表单序列化,前提只是将Form表单中的name属性与数据库的字段名保持一致便 ...

  7. android模拟器与PC的端口映射

    一.概述 Android系统为实现通信将PC电脑IP设置为10.0.2.2,自身设置为127.0.0.1,而PC并没有为Android模拟器系统指定IP,所以PC电脑不能通过IP来直接访问Androi ...

  8. JDBC批量执行executeBatch

    JDBC事务 在数据库中,所谓事务是指一组逻辑操作单元,使数据从一种状态变换到另一种状态.为确保数据库中数据的一致性,数据的操纵应当是离散的成组的逻辑单元:当它全部完成时,数据的一致性可以保持,而当这 ...

  9. jquery.flot.js简介

    JQuery图表插件之Flot Flot是一个Jquery下图表插件,具有简单使用,交互效果,具有吸引力外观特点.目前支持 Internet Explorer 6+, Chrome, Firefox ...

  10. shell 数值计算

    shell中的赋值和操作默认都是字符串处理,在此记下shell中进行数学运算的几个特殊方法,以后用到的时候可以来看,呵呵.   1.错误方法举例   a)   var=1+1   echo $var  ...