zoukankan      html  css  js  c++  java
  • P3842 [TJOI2007]线段 思维 ,DP

    在一个 n*n 的平面上,在每一行中有一条线段,第 i 行的线段的左端点是(i, L(i)),右端点是(i, R(i)),其中 1 ≤ L(i) ≤ R(i) ≤ n。

    你从(1, 1)点出发,要求沿途走过所有的线段,最终到达(n, n)点,且所走的路程长度要尽量短。

    更具体一些说,你在任何时候只能选择向下走一步(行数增加 1)、向左走一步(列数减少 1)或是向右走一步(列数增加 1)。当然,由于你不能向上行走,因此在从任何一行向下走到另一行的时候,你必须保证已经走完本行的那条线段。

    100%的数据中,n ≤ 20 000。

    关键在于想到状态

    用f[i][0]表示走完且在第i行左端点的最短路程,f[i][1]为到右端点的最短路程。

    注意到一个性质:每次下到下一行必然是从左端点或者右端点下降,那么就有f[i][0] = abs(l[i-1] + r[i] + dis(i)) 

    阶段是所在的行

    边界f[1][0]=r[1]+r[1]-l[1]-1,f[1][1]=r[1]-1

    转移方程显然。

    #pragma warning(disable:4996)
    
    #include<iostream>
    #include<algorithm>
    #include<bitset>
    #include<tuple>
    #include<unordered_map>
    #include<fstream>
    #include<iomanip>
    #include<string>
    #include<cmath>
    #include<cstring>
    #include<vector>
    #include<map>
    #include<set>
    #include<list>
    #include<queue>
    #include<stack>
    #include<sstream>
    #include<cstdio>
    #include<ctime>
    #include<cstdlib>
    #define pb push_back
    #define INF 0x3f3f3f3f
    #define inf 0x7FFFFFFF
    #define moD 1000000003
    #define pii pair<ll,ll>
    #define eps 1e-8
    #define equals(a,b) (fabs(a-b)<eps)
    #define bug puts("bug")
    #define re  register
    #define fi first
    #define se second
    typedef  long long ll;
    typedef unsigned long long ull;
    const ll MOD = 1e6 + 7;
    const int maxn = 2e4 +5;
    const double Inf = 10000.0;
    const double PI = acos(-1.0);
    using namespace std;
    
    int readint() {
        int x = 0, f = 1; char ch = getchar();
        while (ch < '0' || ch>'9') { if (ch == '-')f = -1; ch = getchar(); }
        while (ch >= '0' && ch <= '9') { x = x * 10 + ch - '0'; ch = getchar(); }
        return x * f;
    }
    
    void Put(int x)  {
        if (x > 9) Put(x / 10);
        putchar(x % 10 + '0');
    }
    
    int l[maxn];
    int r[maxn];
    int dp[maxn][2];
    
    int main() {
        int n;
        n = readint();
        for (int i = 1; i <= n; i++) l[i] = readint(), r[i] = readint();
        dp[1][0] = r[1] + r[1] - l[1] - 1;
        dp[1][1] = r[1] - 1;
        for (int i = 2; i <= n; i++) {
            dp[i][0] = min(dp[i - 1][0] + abs(l[i - 1] - r[i]) + r[i] - l[i] + 1, dp[i - 1][1] + abs(r[i - 1] - r[i]) + r[i] - l[i] + 1);
            dp[i][1] = min(dp[i - 1][0] + abs(l[i - 1] - l[i]) + r[i] - l[i] + 1, dp[i - 1][1] + abs(r[i - 1] - l[i]) + r[i] - l[i] + 1);
        }
        int ans = min(dp[n][0] + n - l[n], dp[n][1] + n - r[n]);
        Put(ans);
    }
  • 相关阅读:
    Oracle:SQL语句--撤销用户权限
    Oracle:SQL语句--给用户赋权限
    RSTP端口状态迁移过程详解
    LSB算法分析与实现
    工厂方法模式
    Ceasar
    区域性名称和标识符
    Packet Tracer网络模拟实验实记
    H3C-OSPF
    H3C-RIP
  • 原文地址:https://www.cnblogs.com/hznumqf/p/13394599.html
Copyright © 2011-2022 走看看