zoukankan      html  css  js  c++  java
  • P3842 [TJOI2007]线段

    最近多刷些dp,觉得这个算不上蓝题
     
    在一个(n imes n)的平面上,在每一行中有一条线段,第(i)行的线段的左端点是((i, L_i)),右端点是((i, R_i)),其中(1leq L_i leq R_i leq n)
    你从((1, 1))点出发,要求沿途走过所有的线段,最终到达((n, n))点,且所走的路程长度要尽量短。
    更具体一些说,你在任何时候只能选择向下走一步(行数增加 1)、向左走一步(列数减少 1)或是向右走一步(列数增加 1)。当然,由于你不能向上行走,因此在从任何一行向下走到另一行的时候,你必须保证已经走完本行的那条线段。
     


    设计状态,每行走完都会停留在左端点或是右端点,因为不能走不完在中间就停下
    所以考虑将状态设计为(f_{i,0/1}),表示走完了第(i)行,并停留在左端点/右端点
    预处理出第一行的值
    以每一行的(f_{i,0})(走完停留在左端点)为例,因为要停留在左端点,肯定要从右端点开始走
    如果上一行是停留在右端点,则走到右端点的代价为( ext{abs}(R_{i-1}-R_i)+1+f_{i-1,1})
    同样,上一行停留在左端点,走到这一行右端点的代价为( ext{abs}(L_{i-1}-R_i)+1+f_{i-1,0})
    让后当然还要再加上这一行线段的长度
    每行的(f_{i,1})也是同理
    答案显然是(min(f_{n,0}+(n-L_n),f_{n,1}+(n-R_n))),别忘了最后还要走到((n,n))

    #include<cstdio>
    #include<algorithm>
    #include<iostream>
    #include<cmath>
    #include<iomanip>
    #include<cstring>
    #define reg register
    #define EN std::puts("")
    #define LL long long
    inline int read(){
    	int x=0,y=1;
    	char c=std::getchar();
    	while(c<'0'||c>'9'){if(c=='-') y=0;c=std::getchar();}
    	while(c>='0'&&c<='9'){x=x*10+(c^48);c=std::getchar();}
    	return y?x:-x;
    }
    int n;
    LL f[20006][2];
    LL l[20006],r[20006];
    int main(){
    	n=read();
    	for(reg int i=1;i<=n;i++) l[i]=read(),r[i]=read();
    	f[1][0]=r[1]-1+(r[1]-l[1]);f[1][1]=r[1]-1;
    	for(reg int i=2;i<=n;i++){
    		f[i][0]=std::min(f[i-1][0]+std::abs(l[i-1]-r[i])+(r[i]-l[i]),
    			f[i-1][1]+std::abs(r[i-1]-r[i])+(r[i]-l[i]))+1;
    		f[i][1]=std::min(f[i-1][0]+std::abs(l[i-1]-l[i])+(r[i]-l[i]),
    			f[i-1][1]+std::abs(r[i-1]-l[i])+(r[i]-l[i]))+1;
    	}
    	std::printf("%lld",std::min(f[n][0]+n-l[n],f[n][1]+n-r[n]));
    	return 0;
    }
    
  • 相关阅读:
    链表中环的入口节点
    链表中倒数第k个节点
    调整数组顺序使奇数位于偶数前面
    53. Maximum Subarray
    42. Trapping Rain Water
    48. Rotate Image
    css技巧一
    html语义
    label标签表单响应
    CSS清除浮动
  • 原文地址:https://www.cnblogs.com/suxxsfe/p/12527331.html
Copyright © 2011-2022 走看看