题目链接 and 题目大意

hdu3698

但是 hdu的数据比较弱,所以在这luogu提交吧UVA1490 Let the light guide us

有一个\(n*m\)的平原,要求每行选一个点,选\(n\)个点建造塔楼。

平原上每个点都有他自己的花费时间和魔法值。

为了正确控制塔楼,我们必须保证连续两排的每两座塔共用一个共同的魔法区域。

也就是要求每两行相邻的点都满足如下关系:

如果第\(i\)行选\(j\),第\(i+1\)行选\(k\),则需\(|j-k|≤f(i,j)+f(i+1,k)\)。

问花费的总时间最少为多少?

输入\(n,m\)。

再输入两个\(n*m\)的矩阵。

第一个矩阵 $T[i][j] $表示的是花费时间,

第二个矩阵 \(f[i][j]\) 表示的是魔法值\ \

思路\

如果\(m<=100\),那么这题就是个\(O(n*m{2})\)的沙比提\ \

for (int k = 2; k <= n; ++k) {
for (int i = 1; i <= m; ++i) {
for (int j = 1 ; j <= m; ++ j) {
if (abs(i - j) <= f[k][i] + f[k - 1][j] ) {
dp[k][i] = min(dp[k][i], dp[k - 1][j]);
}
}
dp[k][i] += t[k][i];
}
}

但她并是不,\(m<=1000\)

考虑如何优化一下

$abs(i - j) <= f[k][i] + f[k - 1][j] \(
\)abs(i-j)\(就是\)i\(和\)j\(之间的距离
就是\)f[k][i] +f[k-1][j]$ 要大于i和j之间的距离(这里可以当成数轴上面)

我们先看\(k\)这一行

他能给下一行(也就是k+1)提供价值的区间至少为\([i-f[k][i],i+f[k][i])\),或者更大

我们再看\(k+1\)这一行

他能取到的区间(也就是k)的区间至少为\([j-f[k+1][j],j+f[k+1][j])\),或者更大

如果他们的区间有交集,则说明他们可以由\(k\)向\(k+1\)转移

这个就可以用一颗区间加数,区间求min的线段树维护一下

复杂度\(O(n*mlogm)\)

hdu数据很水,要去luogu测!!!

当然,dp方程你可以压维,但压不压的没有啥意义反正你都开了两个一样大的数组了,多开一个又杂

两份代码

暴力代码\(n*m*m\)

#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
const int maxn = 107;
const int maxm = 5007;
const int inf = 0x3f3f3f3f;
int n, m, t[maxn][maxm], f[maxn][maxm], dp[maxn][maxm]; int read() {
int x = 0, f = 1; char s = getchar();
for (; s < '0' || s > '9'; s = getchar()) if (s == '-') f = -1;
for (; s >= '0' && s <= '9'; s = getchar()) x = x * 10 + s - '0';
return x * f;
}
int abs(int a) {
return a > 0 ? a : -a;
} int main() {
while (233) {
// read
n = read(), m = read();
if (n == 0 && m == 0) break;
for (int i = 1; i <= n; ++i)
for (int j = 1; j <= m; ++j)
t[i][j] = read();
for (int i = 1; i <= n; ++i)
for (int j = 1; j <= m; ++j)
f[i][j] = read(); //init
memset(dp, inf, sizeof(dp));
for (int i = 1; i <= m; ++i)
dp[1][i] = t[1][i]; //dp
for (int k = 2; k <= n; ++k) {
for (int i = 1; i <= m; ++i) {
for (int j = 1 ; j <= m; ++ j) {
if (abs(i - j) <= f[k][i] + f[k - 1][j] ) {
dp[k][i] = min(dp[k][i], dp[k - 1][j]);
}
}
dp[k][i] += t[k][i];
}
} //printf
int ans = inf;
for (int i = 1; i <= n; ++i)
ans = min(ans, dp[n][i]);
printf("%d\n", ans);
}
return 0;
}

线段树优化\(n*m*logm\) \\

#include <bits/stdc++.h>
#define ls rt<<1
#define rs rt<<1|1
using namespace std;
const int maxn=107;
const int maxm=5007;
const int inf=0x7fffffff;
int n,m,a[maxn][maxm],b[maxn][maxm],f[maxn][maxm];
struct node {
int l,r;
int mi,lazy;
}e[maxm<<4];
int read() {
int x = 0, f = 1; char s = getchar();
for (; s < '0' || s > '9'; s = getchar()) if (s == '-') f = -1;
for (; s >= '0' && s <= '9'; s = getchar()) x = x * 10 + s - '0';
return x * f;
}
void build(int l,int r,int rt) {
e[rt].l=l,e[rt].r=r,e[rt].mi=inf,e[rt].lazy=inf;
if(l==r) return;
int mid=(l+r)>>1;
build(l,mid,ls);
build(mid+1,r,rs);
}
void pushup(int rt) {
e[rt].mi=min(e[ls].mi,e[rs].mi);
}
void pushdown(int rt) {
if(e[rt].lazy!=inf) {
e[ls].lazy=min(e[ls].lazy,e[rt].lazy);
e[rs].lazy=min(e[rs].lazy,e[rt].lazy);
e[ls].mi=min(e[ls].mi,e[ls].lazy);
e[rs].mi=min(e[rs].mi,e[rs].lazy);
e[rt].lazy=inf;
}
}
void update(int L,int R,int k,int rt) {
if(L<=e[rt].l&&e[rt].r<=R) {
e[rt].lazy=min(e[rt].lazy,k);
e[rt].mi=min(e[rt].mi,e[rt].lazy);
return;
}
pushdown(rt);
int mid=(e[rt].l+e[rt].r)>>1;
if(L<=mid) update(L,R,k,ls);
if(R>mid) update(L,R,k,rs);
pushup(rt);
}
int query(int L,int R,int rt) {
if(L<=e[rt].l&&e[rt].r<=R) {
return e[rt].mi;
}
pushdown(rt);
int mid=(e[rt].l+e[rt].r)>>1,ans=inf;
if(L<=mid) ans=min(ans,query(L,R,ls));
if(R>mid) ans=min(ans,query(L,R,rs));
pushup(rt);
return ans;
}
void debug1() {
printf("debug\n");
printf(" %d\n", e[1].mi);
printf(" %d %d\n", e[2].mi, e[3].mi );
printf(" %d %d %d %d\n", e[4].mi, e[5].mi, e[6].mi, e[7].mi );
printf(" %d %d %d %d %d %d %d %d\n", e[8].mi,
e[9].mi, e[10].mi, e[11].mi, e[12].mi, e[13].mi, e[14].mi, e[15].mi);
}
void debug()
{
for(int i=1;i<=n;++i,puts(""))
for(int j=1;j<=m;++j)
cout<<f[i][j]<<" ";
}
int main()
{
while(1)
{
n=read(),m=read();
if(n==0 && m==0) return 0;
for(int i=1;i<=n;++i)
for(int j=1;j<=m;++j)
a[i][j]=read();
for(int i=1;i<=n;++i)
for(int j=1;j<=m;++j)
b[i][j]=read();
for(int i=1;i<=m;++i)
f[1][i]=a[1][i];
for(int i=2;i<=n;++i) {
build(1,m,1);
for(int j=1;j<=m;++j) {
int l=max(1,j-b[i-1][j]),r=min(m,j+b[i-1][j]);
update(l,r,f[i-1][j],1);
}
for(int j=1;j<=m;++j) {
int l=max(1,j-b[i][j]),r=min(m,j+b[i][j]);
f[i][j]=query(l,r,1)+a[i][j];
}
}
int ans=inf;
for(int i=1;i<=m;++i)
ans=min(ans,f[n][i]);
printf("%d\n", ans);
}
return 0;
}

hdu 3698 UVA1490 Let the light guide us 线段树优化DP的更多相关文章

  1. hdu 3698 Let the light guide us(线段树优化&简单DP)

    Let the light guide us Time Limit: 5000/2000 MS (Java/Others)    Memory Limit: 62768/32768 K (Java/O ...

  2. HDU多校第三场 Hdu6606 Distribution of books 线段树优化DP

    Hdu6606 Distribution of books 题意 把一段连续的数字分成k段,不能有空段且段和段之间不能有间隔,但是可以舍去一部分后缀数字,求\(min(max((\sum ai ))\ ...

  3. hdu 5266 pog loves szh III(lca + 线段树)

    I - pog loves szh III Time Limit:6000MS     Memory Limit:131072KB     64bit IO Format:%I64d & %I ...

  4. HDU 2795 Billboard(宣传栏贴公告,线段树应用)

    HDU 2795 Billboard(宣传栏贴公告,线段树应用) ACM 题目地址:HDU 2795 Billboard 题意:  要在h*w宣传栏上贴公告,每条公告的高度都是为1的,并且每条公告都要 ...

  5. 题解 HDU 3698 Let the light guide us Dp + 线段树优化

    http://acm.hdu.edu.cn/showproblem.php?pid=3698 Let the light guide us Time Limit: 5000/2000 MS (Java ...

  6. hdu3698 Let the light guide us dp+线段树优化

    http://acm.hdu.edu.cn/showproblem.php?pid=3698 Let the light guide us Time Limit: 5000/2000 MS (Java ...

  7. hdu 4521 小明系列问题——小明序列(线段树 or DP)

    题目链接:hdu 4521 本是 dp 的变形,却能用线段树,感觉好强大. 由于 n 有 10^5,用普通的 dp,算法时间复杂度为 O(n2),肯定会超时.所以用线段树进行优化.线段树维护的是区间内 ...

  8. HDU 4521 小明系列问题——小明序列 (线段树维护DP)

    题目地址:HDU 4521 基本思路是DP.找前面数的最大值时能够用线段树来维护节省时间. 因为间隔要大于d. 所以能够用一个队列来延迟更新,来保证每次询问到的都是d个之前的. 代码例如以下: #in ...

  9. hdu 5091 给定矩形覆盖尽量多点 扫描线+线段树

    http://acm.hdu.edu.cn/showproblem.php?pid=5091 给你10000以内的敌舰的坐标(即分别为x,y),要求用W*H的矩形去围住一个区域,使得这个区域内的敌舰最 ...

随机推荐

  1. 匿名内部类的参数引用只能是final,可能遇到的问题及其解决

    这个是我碰到比较多次的问题,一开始是不解,不过查了下大家都觉得没什么,而且只是加个final好像影响也不大,于是我就直接加个final了事,之后也不管了 直到昨天: 遇到了这个宿命般的问题 难道解决方 ...

  2. AspNetPager使用方法

    一.AspNetPager支持两种方式分页: 一种是PostBack方式分页, 一种是通过Url来实现分页以及Url重写功能 二.AspNetPager支持各种数据绑定控件GridView.DataG ...

  3. Android(三) 匹配屏幕密度

    过去,程序员通常以像素为单位设计计算机用户界面.例如:图片大小为80×32像素.这样处理的问题在于,如果在一个dpi(每英寸点数) 高的显示器上运行该程序,则用户界面会显得很小.在有些情况下,用户界面 ...

  4. SQL死锁知识及解决办法

    [翻译]:SQL死锁-死锁排除 min.jiang 2014-03-18 00:23 阅读:874 评论:1     项目中死锁的解决经历 min.jiang 2014-03-17 01:09 阅读: ...

  5. kernel下nand flash的文件系统总结

    1.FLASH转换层(FTL) EXt2/EXT3/EXT4文件系统可以通过FTL实现对flash的支持,因为FTL可以将闪存flash模拟成磁盘结构. 在ext2文件系统的基础上上,为了保证数据的一 ...

  6. PAT 1070 Mooncake[一般]

    1070 Mooncake (25)(25 分) Mooncake is a Chinese bakery product traditionally eaten during the Mid-Aut ...

  7. Bootstrap 网格系统(Grid System)的工作原理 - 媒体查询

    媒体查询 媒体查询是非常别致的"有条件的 CSS 规则".它只适用于一些基于某些规定条件的 CSS.如果满足那些条件,则应用相应的样式. Bootstrap 中的媒体查询允许您基于 ...

  8. RMAN中%d %t %s %u,%p,%c 等代替变量的意义

    backup incremental level 0 database format='LEV0_%d_%t_%U_%s_%p' format=string 文件路径和名称的格式串,其中可包含宏变量: ...

  9. 微信小程序- wx.request请求不到数据

    小程序官方文档手册 https://mp.weixin.qq.com/debug/wxadoc/dev/ 小程序开发问答社区 http://www.henkuai.com/forum.php wx.r ...

  10. 摘要JSR168 PORLET标准手册汉化整理

    本规范汉化资源搜集整理于网上并由我作了些修改和添加,主要为适应大陆的语辞.用语及其他未译之处. 由于本人于水平有限,如有错误,请各位高手指正:若有高见,希望不吝言辞,同为中国开源作项献. 特此严重感谢 ...