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: 唯一的麻烦就是 ...
随机推荐
- break与continue用法注意事项
break 中断循环执行,跳出循环 注意,break只能中断自己所在的循环,一般用在内层循环,但是不能中断外层循环中的代码. continue 跳到循环的下一轮继续执行,结束自己所在循环体代码,继续自 ...
- AJ学IOS 之微博项目实战(3)微博主框架-UIImage防止iOS7之后自动渲染_定义分类
AJ分享,必须精品 一:效果对比 当我们设置tabBarController的tabBarItem.image的时候,默认情况下会出现图片变成蓝色的效果,这是因为ios7之后会对图片自动渲染成蓝色 代 ...
- 自动补全、回滚!介绍一款可视化 sql 诊断利器
Yearning简介 ================= Yearning MYSQL 是一个SQL语句审核平台.提供查询审计,SQL审核等多种功能,支持Mysql,可以在一定程度上解决运维与开发之间 ...
- Feature list, Standard and Test plan for BETA Release 12/22/2015
===================BETA RELEASE FEATRURE LIST==================== 1. Log in and account manager for ...
- ppt和pptx转图片完整代码,解决2003版和2007版中文乱码问题
引入所需依赖,注意poi版本,新版本不支持,最好使用和我一样的版本. <!-- https://mvnrepository.com/artifact/org.apache.poi/poi --& ...
- 基于netty实现rpc框架-spring boot服务端
demo地址 https://gitee.com/syher/grave-netty RPC介绍 首先了解一下RPC:远程过程调用.简单点说就是本地应用可以调用远程服务器的接口.那么通过什么方式调用远 ...
- 使用dynamic 和MEF实现轻量级的 AOP 组件 (1)
转载https://www.cnblogs.com/niceWk/archive/2010/07/19/1780843.html AOP魔法 今天你AOP了吗?谈到AOP,总有一种神秘的感觉,人类对于 ...
- java实现自定义哈希表
哈希表实现原理 哈希表底层是使用数组实现的,因为数组使用下标查找元素很快.所以实现哈希表的关键就是把某种数据类型通过计算变成数组的下标(这个计算就是hashCode()函数 比如,你怎么把一个字符串转 ...
- opencv-1-QT_OPENCV 安装
opencv-1-QT_OPENCV 安装 qtopencvc++ 既然我们是从头开始的, 那我们就从 opencv 的安装开始吧, 主要环境为: win10 1909 - 18363.720 版本 ...
- 基于口令的密码(PBE)
基于口令的密码(PBE) 基于口令的密码(Password Based Encryption,PBE)是一种基于口令生成密钥,并使用该密钥进行加密的方法.其中加密和解密使用的是同一个密钥. 根据用户自 ...