Several days before the exams, but now I think of it tune. .
The meaning of problems
Selected from the lattice, the selected minimum weight requirements, but each selected grid range is limited: abs (jk) <= w [i] [j] + w [i-1] [k] w which is another value
暴力:O(n*m*m*T)
Optimization : For the grid line to be selected, the range over which the row of the grid to cover out process, and then select the row, resulting in the desired rapid grid which can be selected from a range, a minimum weight cell
Then for each line segment tree with a minimum maintenance, to put the next line segment tree emptying, re-modify
#include<bits/stdc++.h> using namespace std; #define mid ((l+r)>>1) #define N 105 #define M 5005 #define inf 0x7f7f7f int a[N][M],dp[N][M],minn[M*4],fl[M*4],l[N][M],r[N][M]; void update(int s) { minn[s]=min(minn[s<<1],minn[s<<1|1]); } void pushdown(int s) { if(fl[s]==inf) return ; minn[s<<1] = min (a [i << 1 ], in [i]); in [s << 1 ] = min (in [s << 1 ], in [i]); from [the << 1 | 1 ] = min (a [i << 1 | 1 ], in [i]); in [the << 1 | 1 ] = min (in [s << 1 | 1 ], in [i]); in [s] = inf; } Void build ( you 's, you're with, you r) { at [s] = inf; ow (l == r) {a [i] = inf; return ;} Build (S << . 1 , L, MID); Build (<< S . 1 | . 1 , MID + . 1 , R & lt); Update (S); } void Modify ( int S, int L, int R & lt, int L , int R & lt, int V) { IF (L <= R & lt && L <= R & lt) { Minn [S] = min (Minn [S], V); // be sure to remember to update! ! FL [S] = min (FL [S], V); return ; } pushdown (S); // Modify query and downstream are marked if(L<=mid) modify(s<<1,l,mid,L,R,v); if(R>mid) modify(s<<1|1,mid+1,r,L,R,v); update(s); } int query(int s,int l,int r,int L,int R) { if(L<=l&&r<=R) return minn[s]; pushdown(s); int ans=inf; if(L<=mid) ans=min(ans,query(s<<1,l,mid,L,R)); if(R>mid) ans=min(ans,query(s<<1|1,mid+1,r,L,R)); return ans; } int main() { freopen("elect.in","r",stdin); freopen("elect.out","w",stdout); int T,n,m; scanf("%d%d%d",&T,&n,&m); while(T--){ int ans=0x7f7f7f; for(int i=1;i<=n;i++) For ( int J = . 1 ; J <= m; J ++ ) Scanf ( " % D " , & A [I] [J]); for ( int I = . 1 ; I <= n-; I ++ ) for ( int J = . 1 ; J <= m; J ++ ) { int X; Scanf ( " % D " , & X); L [I] [J] = max ( . 1 , JX); // for each point of each line is obtained to cover the maximum distance interval to maintain the value of the most segment tree with R & lt [I] [J] = min (m, J + X); } build(1,1,m); for(int i=1;i<=m;i++) dp[1][i]=a[1][i],modify(1,1,m,l[1][i],r[1][i],dp[1][i]); for(int i=2;i<=n;i++){ for(int j=1;j<=m;j++) dp[i][j]=query(1,1, m, L [I] [J], R & lt [I] [J]) + A [I] [J]; Build ( . 1 , . 1 , m); // row corresponding to a segment tree! ! Line after use to rebuild for ( int J = . 1 ; J <= m; J ++ ) Modify ( . 1 , . 1 , m, L [I] [J], R & lt [I] [J], DP [I] [J ]); } for ( int I = . 1 ; I <= m; I ++) ANS = min (ANS, DP [n-] [I]); the printf ( " % D \ n- " , ANS); } } / * . 1 . 3. 5 . 9. 8. 7. 3. 5 . 8. 9 2. 8. 6 . 1. 9. 7. 8. 6 0 0. 1. 1 2 . 1. 1. 1 0 2 0 2. 1 0 2 * /