HDU-3689 Let the light guide us 线段树+DP

2023-11-29 05:38
文章标签 dp hdu 线段 us light guide let 3689

本文主要是介绍HDU-3689 Let the light guide us 线段树+DP,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

题意:输入n,m,然后两个n*m的矩阵,第一个代表在这个位置建塔的成本,第二个代表在相应位置建塔能照的距离,要求每行建一个,并且相邻两行的两个塔要满足照的距离之和大于等于列号差。求最小成本。

分析:每一行中建立一个塔后会在这行照亮一段距离,如果下一行中的一个点能照到这段区间,表示这两个是可以同时建的。也就是下一行中的一个点要在这一行中的对应区间找一个成本最小值,动态规划的状态传递比较好写,只是一行最多有5000个点,照最小值要用线段树优化。

这个题在场上看出来是要用线段树了,本来线段树就比较弱,又很久没有写过了,结果一个半小时都没有写出来,最终补题的时候也是错了好多遍才出,一直TLE,结果最后是因为数组开小了……无语。。。不过最终能手写出来还是挺有成就感的。

#include <string.h>
#include <stdio.h>
int INF = 0x3f3f3f3f;
struct node {int b, e, d, same;
}id[2][22000];
int f[105][5005];
int t[105][5005];
void init(int f, int u, int b, int e) {id[f][u].b = b;id[f][u].e = e;id[f][u].d = INF;id[f][u].same = INF;if(b != e) {int m = (b + e) >> 1;init(f, u << 1, b, m);init(f, (u << 1) + 1, m + 1, e);}
}
void update(int f, int u, int b, int e, int d) {if(d < id[f][u].d)id[f][u].d = d;if(id[f][u].b == b && e == id[f][u].e) {if(id[f][u].same > d)id[f][u].same = d;return;}int m = (id[f][u].b + id[f][u].e) >> 1;int lc = (u << 1), rc = (u << 1) + 1;if(e <= m) {update(f, lc, b, e, d);}else if(b > m)update(f, rc, b, e, d);else{update(f, lc, b, m, d);update(f, rc, m + 1, e, d);}
}
int query(int f, int u, int b, int e) {if((id[f][u].b == b && id[f][u].e == e)) {return id[f][u].d;}if(id[f][u].same <= id[f][u].d)return id[f][u].same;int m = (id[f][u].b + id[f][u].e) >> 1, x, y;int lc = u << 1, rc = (u << 1) + 1;if(e <= m) {x = query(f, lc, b, e);return id[f][u].same < x ? id[f][u].same : x;}else if(b > m) {x = query(f, rc, b, e);return id[f][u].same < x ? id[f][u].same : x;}else{x = query(f, lc, b, m);y = query(f, rc, m + 1, e);x = y < x ? y : x;return id[f][u].same < x ? id[f][u].same : x;}
}
int main() {int n, m, i, j, mn, a, b;while(~scanf("%d%d", &n, &m) && (n || m)) {for(i = 0; i < n; i++){for(j = 0; j < m; j++){scanf("%d", &t[i][j]);}}for(i = 0; i < n; i++){for(j = 0; j < m; j++){scanf("%d", &f[i][j]);}}init(0, 1, 0, m - 1);for(j = 0; j < m; j++) {a = j - f[0][j];b = j + f[0][j];if(a < 0)a = 0;if(b > m - 1)b = m - 1;update(0, 1, a, b, t[0][j]);}for(i = 1; i < n; i++) {init(i & 1, 1, 0, m - 1);for(j = 0; j < m; j++){a = j - f[i][j];b = j + f[i][j];if(a < 0)a = 0;if(b > m - 1)b = m - 1;mn = query(((~i) & 1), 1, a, b);update((i & 1), 1, a, b, t[i][j] + mn);}}printf("%d\n", query((~n) & 1, 1, 0, m - 1));}return 0;
}

这篇关于HDU-3689 Let the light guide us 线段树+DP的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/431673

相关文章

Apple - Media Playback Programming Guide

本文翻译整理自:Media Playback Programming Guide(Updated: 2018-01-16 https://developer.apple.com/library/archive/documentation/AudioVideo/Conceptual/MediaPlaybackGuide/Contents/Resources/en.lproj/Introduction

上海邀请赛 A题目 HDU 5236(dp)

先求出没有ctrl+s的时候构造长度为i的期望f[i] 。然后枚举保存的次数,求出最小即可。 #include<cstdio>#include<cstdio>#include<cmath>#include<queue>#include<stack>#include<string>#include<cstring>#include<iostream>#include<map>

hdu 2586 树上点对最近距离 (lca)

,只要知道dis[i][j]=dis[i][root]+dis[j][root]-2*dis[Lca(i,j)][root].   其中root为树的根节点,LCA(i,j)为i,j的最近公共祖先。 所以我们先把所有的询问储存下来,然后离线直接查询。复杂度是o(n+q)的。 VIE #include<cstdio>#include<algorithm>#include<i

poj 3160 Father Christmas flymouse 强连通+dp

首先我们可以确定的是,对于val值小于0的节点都变成0.   假设一个集合内2个房间都能任意到达,那么我就可以吧集合内的所有点的价值都取到,并且可以达到任一点。实际上集合内的每个点是相同的,这样的集合就是一个强连通分量。 那么我们就可以用tarjin算法进行强连通缩点, 最后形成一个dag的图。在dag的图上面进行dp。可以先用拓扑排序后dp。或者建反响边记忆化搜索 。 VIEW

秋招突击——6/22——复习{区间DP——加分二叉树,背包问题——买书}——新作{移除元素、实现strStr()}

文章目录 引言复习区间DP——加分二叉树个人实现 背包问题——买书个人实现参考实现 新作移除元素个人实现参考思路 找出字符串中第一个匹配项的下标个人实现参考实现 总结 引言 今天做了一个噩梦,然后流了一身汗,然后没起来,九点多才起床背书。十点钟才开始把昨天那道题题目过一遍,然后十一点才开始复习题目,为了不耽误下午的时间,所以这里的就单纯做已经做过的题目,主打一个有量,不在学

使用Let‘s Encrypt 申请通配符证书

为什么不使用阿里云/腾讯云等公有云厂商提供的免费证书? 上篇介绍了从阿里云上面申请免费证书,有效期一年 为网站配置https证书 公有云提供的证书不支持通配符,只支持某个确定的解析。 不管是二级域名还是三级域名,只要是具体的确定的地址,都可以使用。 对于某个域名,如果DNS解析很少,如只有mail.abc.com,www.abc.com,blog.abc.com, 用公有云需要分别为

ORA-12737: Instant Client Light: unsupported server character set CHS16GBK

当使用Navicat Premiun 英文版连接oracl时可能会报ORA-12737: Instant Client Light: unsupported server character set CHS16GBK错误 这是只要打开Navicat Premiun-->tools-->options 把OCI的地址指向oracle安装目录下的oci.dll即可,地址可能不完全相同,我的是在:F:

动态规划DP--斐波那契数、爬楼梯、使用最小花费爬楼梯等示例代码

动态规划DP 文章目录 动态规划DP509. 斐波那契数70. 爬楼梯746. 使用最小花费爬楼梯62. 不同路径63. 不同路径II343.整数拆分 509. 斐波那契数 509. 斐波那契数 斐波那契数 (通常用 F(n) 表示)形成的序列称为 斐波那契数列 。该数列由 0 和 1 开始,后面的每一项数字都是前面两项数字的和。也就是: F(0) = 0,F(1) =

线段树单点修改的应用

思路:对初始状态进行建树,然后这题就相当于查询第一个合法的位置,并且对其值进行修改,整个题目要求维护的是区间最大值,很显然可以使用线段树。 #include <bits/stdc++.h>using namespace std;const int N = 2e6 + 5;typedef long long ll;typedef pair<ll, ll> pll;typedef arra

HDU_1013

这个题目尤其需要注意的是开始输入的时候的数的大小,开始输入时有可能非常的大超过了长整型的范围,所以不能开始用整形来存放输入的,,就是开始的时候没有注意到这个问题所以开始的时候一直没有AC,后来就是用一个数组接收输入,然后在经过第一步转化之后就可以用一个整数来装了 #include <iostream>#include <stdlib.h>#include <string>usin