E - Help Jimmy POJ - 1661 dp
E - Help Jimmy
这个题目本身不是很难,但是可以更加优化这个写法。
开始是n*n
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <algorithm>
#include <cstdlib>
#include <vector>
#include <stack>
#include <queue>
#include <map>
#include <string>
#define inf 0x3f3f3f3f
#define inf64 0x3f3f3f3f3f3f3f3f
using namespace std;
typedef long long ll;
const int maxn = 1e3 + ;
int dp[maxn][];
struct node {
int l, r, h;
node(int x = , int y = , int h = ) :l(x), r(y), h(h) {}
}ex[maxn]; bool cmp(node a, node b) {
return a.h > b.h;
}
int main() {
int t;
scanf("%d", &t);
while (t--) {
int n, x, y, maxs, ans = inf, flag = ;
memset(dp, inf, sizeof(dp));
scanf("%d%d%d%d", &n, &x, &y, &maxs);
for (int i = ; i <= n; i++) {
int a, b, w;
scanf("%d%d%d", &a, &b, &w);
if (a > b) swap(a, b);
ex[i] = node(a, b, w);
}
sort(ex + , ex + + n, cmp);
for (int i = ; i <= n; i++) {
if (ex[i].l <= x && ex[i].r >= x && ex[i].h <= y) {
flag = ;
dp[i][] = y - ex[i].h + abs(ex[i].l - x);
dp[i][] = y - ex[i].h + abs(ex[i].r - x);
// printf("l=%d r=%d\n", ex[i].l, ex[i].r);
// printf("dp[%d]=%d dp[%d]=%d %d\n", i, dp[i][0], i, dp[i][1], ex[i].h);
break;
}
}
if (flag == && y <= maxs) {
printf("%d\n", y);
continue;
}
for (int i = ; i <= n; i++) {
int flag1 = , flag2 = ;
if (dp[i][] >= inf || dp[i][] >= inf) continue;
for (int j = ; j <= n; j++) {
if (i == j) continue;
if (ex[j].h > ex[i].h) continue;
int h = ex[i].h - ex[j].h;
if (h > maxs) continue; if (ex[i].l <= ex[j].r&&ex[i].l >= ex[j].l&&flag1 == ) {
flag1 = ;
dp[j][] = min(dp[j][], dp[i][] + abs(ex[i].l - ex[j].l) + h);
dp[j][] = min(dp[j][], dp[i][] + abs(ex[i].l - ex[j].r) + h);
// printf("l=%d l=%d h=%d\n", ex[i].l, ex[j].l, h);
// printf("ww dp[%d][0]=%d dp[%d][1]=%d %d\n", j, dp[j][0], j, dp[j][1], ex[j].h);
} if (ex[i].r <= ex[j].r&&ex[i].r >= ex[j].l&&flag2 == ) {
flag2 = ;
dp[j][] = min(dp[j][], dp[i][] + abs(ex[i].r - ex[j].l) + h);
dp[j][] = min(dp[j][], dp[i][] + abs(ex[i].r - ex[j].r) + h);
// printf("zz dp[%d][0]=%d dp[%d][1]=%d %d\n", j, dp[j][0], j, dp[j][1], ex[j].h);
} }
if (flag1 == && ex[i].h <= maxs) ans = min(ans, dp[i][] + ex[i].h);
if (flag2 == && ex[i].h <= maxs) ans = min(ans, dp[i][] + ex[i].h);
}
printf("%d\n", ans);
}
return ;
}
不把起点和终点当成平台的n*n
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <algorithm>
#include <cstdlib>
#include <vector>
#include <stack>
#include <queue>
#include <map>
#include <string>
#define inf 0x3f3f3f3f
#define inf64 0x3f3f3f3f3f3f3f3f
using namespace std;
typedef long long ll;
const int maxn = 1e3 + ;
int dp[maxn][];
struct node {
int l, r, h;
node(int x = , int y = , int h = ) :l(x), r(y), h(h) {}
}ex[maxn]; bool cmp(node a,node b)
{
return a.h > b.h;
}
int main() {
int t;
scanf("%d", &t);
while (t--) {
int n, x, y, maxs, ans = inf;
memset(dp, inf, sizeof(dp));
scanf("%d%d%d%d", &n, &x, &y, &maxs);
for (int i = ; i <= n; i++) {
int a, b, w;
scanf("%d%d%d", &a, &b, &w);
if (w >= y) continue;
if (a > b) swap(a, b);
ex[i] = node(a, b, w);
}
ex[++n] = node(x, x, y);
ex[++n] = node(-inf, inf, );
sort(ex + , ex + + n, cmp);
dp[][] = , dp[][] = ;
for (int i = ; i <= n; i++) {
int flag1 = , flag2 = ;
if (dp[i][] >= inf || dp[i][] >= inf) continue;
for (int j = i+; j <= n; j++) {
if (ex[j].h >= ex[i].h) continue;
int h = ex[i].h - ex[j].h;
if (h > maxs) continue; if (ex[i].l <= ex[j].r&&ex[i].l >= ex[j].l&&flag1 == ) {
flag1 = ;
int val1 = abs(ex[i].l - ex[j].l);
int val2 = abs(ex[i].l - ex[j].r);
if (i == n || j == n) val1 = val2 = ;
dp[j][] = min(dp[j][], dp[i][] + val1 + h);
dp[j][] = min(dp[j][], dp[i][] + val2 + h);
// printf("l=%d l=%d h=%d\n", ex[i].l, ex[j].l, h);
// printf("ww dp[%d][0]=%d dp[%d][1]=%d %d\n", j, dp[j][0], j, dp[j][1], ex[j].h);
} if (ex[i].r <= ex[j].r&&ex[i].r >= ex[j].l&&flag2 == ) {
flag2 = ;
int val1 = abs(ex[i].r - ex[j].l);
int val2 = abs(ex[i].r - ex[j].r);
if (i == n || j == n) val1 = val2 = ;
dp[j][] = min(dp[j][], dp[i][] + val1 + h);
dp[j][] = min(dp[j][], dp[i][] + val2 + h);
// printf("zz dp[%d][0]=%d dp[%d][1]=%d %d\n", j, dp[j][0], j, dp[j][1], ex[j].h);
} }
}
printf("%d\n", min(dp[n][],dp[n][]));
}
return ;
}
把起点和终点当成平台的n*n
然后这个题目可以用线段树优化成 n*logn+n 的复杂度。
这个是因为每一个平台会落到的平台是固定的,所以可以用线段树预处理出来每一个平台的下一个平台。
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <queue>
#include <vector>
#include <string>
#include <algorithm>
#include <iostream>
#include <map>
#define inf 0x3f3f3f3f
#define inf64 0x3f3f3f3f3f3f3f3f
using namespace std;
typedef long long ll;
const int M = 2e4 + ;
const int maxn = 2e3 + ;
struct node
{
int id, l, r, lx, rx, y;
node(int id=,int l=,int r=,int lx=,int rx=,int y=):id(id),l(l),r(r),lx(lx),rx(rx),y(y){}
}ex[maxn];
int p[maxn];
ll dp[maxn][];
bool cmp(int a,int b)
{
return ex[a].y < ex[b].y;
}
bool cmp1(int a, int b) {
return ex[a].y > ex[b].y;
}
int sum[M * ], lazy[M * ]; void build(int id,int l,int r)
{
sum[id] = lazy[id] = ;
if (l == r) return;
int mid = (l + r) >> ;
build(id << , l, mid);
build(id << | , mid + , r);
} void push_down(int id)
{
if (lazy[id] == ) return;
sum[id << ] = lazy[id];
sum[id << | ] = lazy[id];
lazy[id << ] = lazy[id << | ] = lazy[id];
lazy[id] = ;
} void update(int id,int l,int r,int x,int y,int val)
{
// printf("id=%d l=%d r=%d x=%d y=%d\n", id, l, r, x, y);
if(x<=l&&y>=r)
{
lazy[id] = val;
sum[id] = val;
return;
}
push_down(id);
int mid = (l + r) >> ;
if (x <= mid) update(id << , l, mid, x, y, val);
if (y > mid) update(id << | , mid + , r, x, y, val);
} int query(int id,int l,int r,int pos)
{
if (l == r) return sum[id];
int mid = (l + r) >> ;
push_down(id);
if (pos <= mid) return query(id << , l, mid, pos);
return query(id << | , mid + , r, pos);
} int main()
{
int t;
scanf("%d", &t);
while(t--)
{
memset(dp, inf, sizeof(dp));
int N, X, Y, H;
scanf("%d%d%d%d", &N, &X, &Y, &H);
X += M;
for(int i=;i<=N;i++)
{
p[i] = i;
int l, r, h;
scanf("%d%d%d", &l, &r, &h);
l += M, r += M;
ex[i] = node(i, l, r, , , h);
}
N++;
p[N] = N;
ex[N] = node(, -inf, inf, , , );
build(, , M * );
sort(p + , p + + N, cmp);
for(int i=;i<=N;i++)
{
// printf("i=%d p=%d\n", i, p[i]);
int l = ex[p[i]].l, r = ex[p[i]].r, id = ex[p[i]].id;
ex[p[i]].lx = query(, , M*, l);
ex[p[i]].rx = query(, , M*, r);
// printf("l=%d r=%d\n", l, r);
// printf("ex[%d] lx=%d rx=%d\n", p[i], ex[p[i]].lx, ex[p[i]].rx);
update(, , M*, l, r, id);
}
int num = query(, , M*, X);
if(num==)
{
printf("%d\n", Y);
continue;
}
dp[num][] = Y - ex[num].y + abs(X - ex[num].l);
dp[num][] = Y - ex[num].y + abs(X - ex[num].r);
// printf("num=%d\n", num);
// printf("dp[%d][0]=%lld dp[%d][1]=%lld\n\n", num, dp[num][0], num, dp[num][1]);
sort(p + , p + + N, cmp1);
for(int i=;i<=N;i++)
{
int id = ex[p[i]].id;
// printf("p[%d]=%d id=%d\n", i, p[i], id);
if (dp[id][] >= inf) continue;
int lx = ex[id].lx;
int rx = ex[id].rx;
if(ex[id].y-ex[lx].y<=H)
{
int val = abs(ex[id].l - ex[lx].l);
if (lx == ) val = ;
dp[lx][] = min(dp[lx][], dp[id][] + ex[id].y - ex[lx].y + val);
val = abs(ex[id].l - ex[lx].r);
if (lx == ) val = ;
dp[lx][] = min(dp[lx][], dp[id][] + ex[id].y - ex[lx].y + val);
}
if(ex[id].y-ex[rx].y<=H)
{
int val = abs(ex[id].r - ex[rx].l);
if (rx == ) val = ;
dp[rx][] = min(dp[rx][], dp[id][] + ex[id].y - ex[rx].y + val);
val = abs(ex[id].r - ex[rx].r);
if (rx == ) val = ;
dp[rx][] = min(dp[rx][], dp[id][] + ex[id].y - ex[rx].y + val);
}
// printf("dp[%d][0]=%lld dp[%d][1]=%lld\n", lx, dp[lx][0], lx, dp[lx][1]);
// printf("dp[%d][0]=%lld dp[%d][1]=%lld\n\n", rx, dp[rx][0], rx, dp[rx][1]);
}
printf("%lld\n", min(dp[][], dp[][]));
}
return ;
}
线段树 n*logn+n
还应该可以直接把dp放到线段树里面,就只有n*logn的复杂度。
这个暂时不想写了。
E - Help Jimmy POJ - 1661 dp的更多相关文章
- Help Jimmy POJ - 1661 dp
#include<iostream> #include<stdio.h> #include<algorithm> #include<cstring> u ...
- Help Jimmy POJ - 1661 数字三角DP
题意:中文 https://vjudge.net/problem/POJ-1661 题解:设两个dp数组,dpl[i]存 从第i块板左边到地上所花的最短时间,dpr[i]存右边的. 将所有板按高度排序 ...
- POJ 1661 DP
Help Jimmy Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 11071 Accepted: 3607 Descr ...
- POJ 1661 Help Jimmy(递推DP)
思路: 1. 每个板子有左右两端, dp[i][0], dp[i][1] 分别记录左右端到地面的时间 2. 从下到上递推计算, 上一层的板子必然会落到下面的某一层板子上, 或者地面上 总结: 1. 计 ...
- POJ 1661 Help Jimmy(C)动态规划
没刷过 POJ,这题是论坛有人问的,我才看看. 我发现 POJ 注册很奇怪,账号总是登不上去,弄的我还注册两个.Emmm 首次体验很差,还好我不在 POJ 刷题. 题目链接:POJ 1661 Help ...
- POJ 1661 Help Jimmy(二维DP)
题目链接:http://poj.org/problem?id=1661 题目大意: 如图包括多个长度和高度各不相同的平台.地面是最低的平台,高度为零,长度无限. Jimmy老鼠在时刻0从高于所有平台的 ...
- POJ - 1661 - Help Jimmy - 简单dp
http://poj.org/problem?id=1661 一般化处理,把一开始的落地和大地都视作平台,设计平台类的属性.dp的时候显然是从上往下dp的,而且要小心Jimmy不能够穿过平台,也就是从 ...
- POJ 1661 Help Jimmy【DP】
基础DP,过程想明白了其实也不复杂,从上面的推下面的比倒着推要简单很多.调试了半个多小时..简单dp依然不能快速AC..SAD.. 题目链接: http://poj.org/problem?id=16 ...
- POJ 1661 Help Jimmy LIS DP
http://poj.org/problem?id=1661 对板按高度排序后. dp[i][0]表示现在站在第i块板上,向左跑了,的状态,记录下时间和其他信息. O(n^2)LIS: 唯一的麻烦就是 ...
随机推荐
- 同步工具类—— CountDownLatch
本博客系列是学习并发编程过程中的记录总结.由于文章比较多,写的时间也比较散,所以我整理了个目录贴(传送门),方便查阅. 并发编程系列博客传送门 CountDownLatch简介 CountDownLa ...
- HTTPS工作流程
HTTPS工作流程 RSA算法 RSA的密钥分成两个部分: PublicKey 加密数据 验证签名 不能解密 任何人都可以获得 Private Key 数据签名(摘要算法) 解密 加密(不用此功能) ...
- Three.js三维模型几何体旋转、缩放和平移
创建场景中的三维模型往往需要设置显示大小.位置.角度,three.js提供了一系列网格模型对象的几何变换方法,从WebGL的角度看,旋转.缩放.平移对应的都是模型变换矩阵,关于矩阵变换内容可以观看本人 ...
- 1196F - K-th Path
题目链接: http://codeforces.com/problemset/problem/1196/F 题目大意::无向图,求任意两点第k短的路径 思路:按照边的大小,只保留前K个边,如果不连同的 ...
- D - Free Candies UVA - 10118
题目链接:https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem ...
- 将函数作为返回值的方法 - Python
有的时候,我们需要将函数作为返回值,以下为代码: def superfunc(): i = 0 def wrapper(): nonlocal i i +=1 return i return wrap ...
- JavaScript函数作用域和声明提前(3.10.1 page.57)
<h4>3.函数作用域和声明提前</h4> <p> <!--<script type="text/javascript">-- ...
- [WEB前置技能]HTTP协议
HTTP概述 HTTP协议是Hyper Text Transfer Protocol(超文本传输协议)的缩写,是用于从万维网(WWW:World Wide Web )服务器传输超文本到本地浏览器的传送 ...
- pytorch seq2seq闲聊机器人加入attention机制
attention.py """ 实现attention """ import torch import torch.nn as nn im ...
- 关于synergy的问题
报错信息主要集中在以下两条: ERROR: ssl error occurred (system call failure) ERROR: eof violates ssl protocol 通过查找 ...