zoukankan      html  css  js  c++  java
  • Problem 4 dp

    $des$

    小 $Y$ 十分喜爱光学相关的问题, 一天他正在研究折射.
    他在平面上放置了 $n$ 个折射装置, 希望利用这些装置画出美丽的折线.
    折线将从某个装置出发, 并且在经过一处装置时可以转向, 若经过的装置坐
    标依次为 $(x_1, y_1), (x_2, y_2) ... (x_k, y_k ),$ 则必须满足:
    $ullet forall j in (1, k], y_j < y_{j - 1}$
    $ullet forall j in (2, k], x_{j - 2} < x_{j} < x_{j - 1} 或者 x_{j - 1} < x_j < x_{j - 2}$
    求不同种的画法

    $sol$

    按 $x$ 坐标排序,$f_{i, 0/1}$ 表示以第 $i$ 个点为顶端下来向左或向右的折线的方案数
    从左到右加点,考虑前 $i$ 个点构成的包含 $i$ 点的折线,由于新点横坐标最大, 所以只可能在折线的
    第一位或第二位:
    1. $forall y_j < y_i, f_{i, 0} gets f_{j, 1}$
    2. $forall y_j > y_i, f_{j, 1} gets f_{k, 0} | x_k > x_j 且 y_k < y_i$
    第二种情况可以前缀和优化, 复杂度 $O(n^2)$

    $code$

    #include <bits/stdc++.h>
    
    using std::pair;
    
    typedef long long ll;
    typedef pair<int, int> pii;
    
    #define fst first
    #define snd second
    
    const int oo = 0x3f3f3f3f;
    
    #define gc getchar()
    inline int read() {
        int x = 0; char c = gc;
        while(c < '0' || c > '9') c = gc;
        while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = gc;
        return x;
    }
    
    const int N = 6000;
    const int mo = 1e9 + 7;
    
    pii p[N + 5];
    int dp[N + 5][2], n;
    
    int main() {
        n = read();
        for(int i = 1; i <= n; i++) p[i].fst = read(), p[i].snd = read();
        sort(p + 1, p + n + 1);
        for(int i = 1; i <= n; i++) {
            dp[i][0] = dp[i][1] = 1;
            for(int j = i - 1; j >= 1; j--)
                if(p[j].snd > p[i].snd) (dp[j][1] += dp[i][0]) %= mo;
                else (dp[i][0] += dp[j][1]) %= mo;
        }
        int ans = mo - n;
        for(int i = 1; i <= n; i++) ans = ((ans + dp[i][0]) % mo + dp[i][1]) % mo;
        std:: cout << ans;
        return 0;
    }
  • 相关阅读:
    Beta冲刺——星期四
    Beta冲刺——星期三
    团队学期总结
    Beta版本发布
    第三天Beta冲刺
    第二天Beta冲刺
    第一天Beta冲刺
    个人作业——Alpha项目测试
    第四次团队作业
    第三次团队作业
  • 原文地址:https://www.cnblogs.com/shandongs1/p/9768845.html
Copyright © 2011-2022 走看看