zoukankan      html  css  js  c++  java
  • hdu3698 Let the light guide us(dp+线段树)

    题意:在每行上选一个点,每个点都要各自对应的代价,同时相邻两行的点要满足 |j-k|≤f(i,j)+f(i+1,k)。问最小代价是多少。

    题解:

    不难发现这是一道dp,状态转移方程如下$dp[i][j]=min{dp[i-1][k]}+t[i][j](|j-k|≤f(i,j)+f(i+1,k))$

    然而如果直接进行转移是要T飞的

    所以如何快速求$k$呢?

    可以发现,$dp[i-1][k]$只会对一个区间的答案产生影响,而$dp[i][j]$的答案必定是一个区间中的最小值加上自己的时间

    于是就是区间修改和区间查询了,之间上线段树

    ps:因为$dp$数组每一行都会更新,实际上可以省掉第一维的空间

     1 //minamoto
     2 #include<cstdio>
     3 #include<iostream>
     4 using namespace std;
     5 #define getc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
     6 char buf[1<<21],*p1=buf,*p2=buf;
     7 template<class T>inline bool cmin(T&a,const T&b){return a>b?a=b,1:0;}
     8 inline int read(){
     9     #define num ch-'0'
    10     char ch;bool flag=0;int res;
    11     while(!isdigit(ch=getc()))
    12     (ch=='-')&&(flag=true);
    13     for(res=num;isdigit(ch=getc());res=res*10+num);
    14     (flag)&&(res=-res);
    15     #undef num
    16     return res;
    17 }
    18 char sr[1<<21],z[20];int C=-1,Z;
    19 inline void Ot(){fwrite(sr,1,C+1,stdout),C=-1;}
    20 inline void print(int x){
    21     if(C>1<<20)Ot();if(x<0)sr[++C]=45,x=-x;
    22     while(z[++Z]=x%10+48,x/=10);
    23     while(sr[++C]=z[Z],--Z);sr[++C]='
    ';
    24 }
    25 const int N=105,M=5005,inf=0x3f3f3f3f;
    26 int t[N][M],f[N][M],dp[M],sum[M<<2],add[M<<2];
    27 int n,m;
    28 void pushdown(int p){
    29     if(add[p]!=inf){
    30         cmin(add[p<<1],add[p]),cmin(add[p<<1|1],add[p]);
    31         cmin(sum[p<<1],add[p<<1]),cmin(sum[p<<1|1],add[p<<1|1]);
    32         add[p]=inf;
    33     }
    34 }
    35 void build(int l,int r,int p){
    36     sum[p]=add[p]=inf;
    37     if(l==r) return;
    38     int mid=l+r>>1;
    39     build(l,mid,p<<1),build(mid+1,r,p<<1|1);
    40 }
    41 void update(int ql,int qr,int x,int l,int r,int p){
    42     if(ql<=l&&qr>=r){
    43         cmin(add[p],x),cmin(sum[p],add[p]);return;
    44     }
    45     int mid=l+r>>1;
    46     pushdown(p);
    47     if(ql<=mid) update(ql,qr,x,l,mid,p<<1);
    48     if(qr>mid) update(ql,qr,x,mid+1,r,p<<1|1);
    49     sum[p]=min(sum[p<<1],sum[p<<1|1]);
    50 }
    51 int query(int ql,int qr,int l,int r,int p){
    52     if(ql<=l&&qr>=r) return sum[p];
    53     int mid=l+r>>1;
    54     pushdown(p);
    55     int res=inf;
    56     if(ql<=mid) cmin(res,query(ql,qr,l,mid,p<<1));
    57     if(qr>mid) cmin(res,query(ql,qr,mid+1,r,p<<1|1));
    58     return res;
    59 }
    60 int main(){
    61     //freopen("testdata.in","r",stdin);
    62     while(true){
    63         n=read(),m=read();
    64         if(n==0&&m==0) break;
    65         for(int i=1;i<=n;++i)
    66         for(int j=1;j<=m;++j)
    67         t[i][j]=read();
    68         for(int i=1;i<=n;++i)
    69         for(int j=1;j<=m;++j)
    70         f[i][j]=read();
    71         for(int i=1;i<=m;++i) dp[i]=t[1][i];
    72         for(int i=2;i<=n;++i){
    73             build(1,m,1);
    74             for(int j=1;j<=m;++j)
    75             update(j-f[i-1][j],j+f[i-1][j],dp[j],1,m,1);
    76             for(int j=1;j<=m;++j)
    77             dp[j]=query(j-f[i][j],j+f[i][j],1,m,1)+t[i][j];
    78         }
    79         int ans=inf;
    80         for(int i=1;i<=m;++i) cmin(ans,dp[i]);
    81         print(ans);
    82     }
    83     Ot();
    84     return 0;
    85 }
  • 相关阅读:
    CSS
    回归分析过程实例(练习)
    结构方程模型处理二阶混合型(反映性+形成性)构念的方法
    python 列表推导式
    python3的enumerate函数
    SecureCRT上传下载文件
    scrapy连接MongoDB
    scrapy连接MySQL
    在Pycharm中运行Scrapy爬虫项目的基本操作
    mysql基础操作学习笔记(2)----索引
  • 原文地址:https://www.cnblogs.com/bztMinamoto/p/9462694.html
Copyright © 2011-2022 走看看