dp+线段树优化-hdu-3698-Let the light guide us
2013-10-06 17:43
363 查看
题目链接:
http://acm.hdu.edu.cn/showproblem.php?pid=3698
题目意思:
给两个n*m矩阵,一个是t矩阵,一个是f矩阵。在矩阵中每行选择一个位置,使相邻两行位置满足关系|j-k|<=f[i,j]+f[i+1,k].且使t值最小。
解题思路:
dp+线段树优化。
dp很容易想到。dp[i][j]=min(dp[i-1][k]+t[i][j]) //其中k和j满足上述关系。
本题的关键是将关系|j-k|<=f[i,j]+f[i+1,k]等价处理,等价于区间【k-f[i-1][k],k+f[i-1][k]】与区间【j-f[i-1][j],j+f[i][j]】有交集。所以可以把钱一行的dp值压入线段树中,使得该区间的最大值小于等于该dp值,然后再查询下一行的区间,如果两区间有交叉的地方一定可以查到。
线段树区间维护一个最小值以及该区间更新的值,注意更新的值要下传给左右区间。
代码:
http://acm.hdu.edu.cn/showproblem.php?pid=3698
题目意思:
给两个n*m矩阵,一个是t矩阵,一个是f矩阵。在矩阵中每行选择一个位置,使相邻两行位置满足关系|j-k|<=f[i,j]+f[i+1,k].且使t值最小。
解题思路:
dp+线段树优化。
dp很容易想到。dp[i][j]=min(dp[i-1][k]+t[i][j]) //其中k和j满足上述关系。
本题的关键是将关系|j-k|<=f[i,j]+f[i+1,k]等价处理,等价于区间【k-f[i-1][k],k+f[i-1][k]】与区间【j-f[i-1][j],j+f[i][j]】有交集。所以可以把钱一行的dp值压入线段树中,使得该区间的最大值小于等于该dp值,然后再查询下一行的区间,如果两区间有交叉的地方一定可以查到。
线段树区间维护一个最小值以及该区间更新的值,注意更新的值要下传给左右区间。
代码:
#include<iostream> #include<cmath> #include<cstdio> #include<sstream> #include<cstdlib> #include<string> #include<cstring> #include<algorithm> #include<vector> #include<map> #include<set> #include<stack> #include<list> #include<queue> #include<ctime> #include<bitset> #define eps 1e-6 #define INF 0x3f3f3f3f #define PI acos(-1.0) #define ll __int64 #define LL long long #define lson l,m,(rt<<1) #define rson m+1,r,(rt<<1)|1 #define M 1000000007 #pragma comment(linker, "/STACK:1024000000,1024000000") using namespace std; #define Maxn 110 #define Maxm 5100 int dp[Maxm]; struct Node { int Min,add; }node[Maxm<<2]; void build(int l,int r,int rt) { node[rt].Min=node[rt].add=INF; if(l==r) return ; int m=(l+r)>>1; build(lson); build(rson); } void pushup(int rt) { node[rt].Min=min(node[rt<<1].Min,node[rt<<1|1].Min); } void pushdown(int rt) { if(node[rt].add!=INF) { node[rt<<1].add=min(node[rt<<1].add,node[rt].add); node[rt<<1].Min=min(node[rt<<1].Min,node[rt].add); node[rt<<1|1].add=min(node[rt<<1|1].add,node[rt].add); node[rt<<1|1].Min=min(node[rt<<1|1].Min,node[rt].add); node[rt].add=INF; } } void update(int l,int r,int rt,int L,int R,int va) { if(L<=l&&R>=r) { node[rt].add=min(node[rt].add,va); node[rt].Min=min(node[rt].Min,va); return ; } int m=(l+r)>>1; pushdown(rt); if(L<=m) update(lson,L,R,va); if(R>m) update(rson,L,R,va); pushup(rt); } int query(int l,int r,int rt,int L,int R) { if(L<=l&&R>=r) return node[rt].Min; int m=(l+r)>>1; pushdown(rt); int res=INF; if(L<=m) res=min(res,query(lson,L,R)); if(R>m) res=min(res,query(rson,L,R)); return res; } int t[Maxn][Maxm],f[Maxn][Maxm]; int main() { int n,m; while(scanf("%d%d",&n,&m)&&n+m) { for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) scanf("%d",&t[i][j]); for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) scanf("%d",&f[i][j]); for(int i=1;i<=m;i++) dp[i]=t[1][i]; for(int i=1;i<=n-1;i++) { build(1,m,1); for(int j=1;j<=m;j++) update(1,m,1,j-f[i][j],j+f[i][j],dp[j]); for(int j=1;j<=m;j++) dp[j]=query(1,m,1,j-f[i+1][j],j+f[i+1][j])+t[i+1][j]; } int ans=INF; for(int i=1;i<=m;i++) ans=min(ans,dp[i]); printf("%d\n",ans); } return 0; }
相关文章推荐
- HDU 3698 Let the light guide us 线段树求区间优化dp
- hdu 3698 Let the light guide us(线段树优化&简单DP)
- HDU 3698 Let the light guide us
- hdu 3698 Let the light guide us【线段树+dp】 2010 Asia Fuzhou Regional Contest
- hdu3698——Let the light guide us
- 【HDU】3698 Let the light guide us 线段树+DP
- HDU 3698 Let the light guide us(DP+线段树)(2010 Asia Fuzhou Regional Contest)
- HDU 3698-Let the light guide us(线段树+DP)愿圣光忽悠你
- HDU-3689 Let the light guide us 线段树+DP
- Let the light guide us HDU
- LA5106: Let the light guide us
- 【DP+线段树】 hdu3698 Let the light guide us
- dp+segtree _ fz2010_Let the light guide us
- hdu3698 Let the light guide us
- hdu3698 Let the light guide us(dp+线段树)
- HDU-4276 The Ghost Blows Light (树形DP+背包)
- HDU 5125 magic balls(dp+线段树优化)
- hdu 3450 离散化+dp+线段树优化
- HDU 4521 小明系列问题——小明序列【dp+线段树优化||最长递增序列】
- *(中等) 树形dp+分组背包 HDU 4276 The Ghost Blows Light