zoukankan      html  css  js  c++  java
  • dp+分类讨论 Gym 101128E

    题目链接:http://codeforces.com/gym/101128

    感觉这个人写的不错的(我只看了题目大意):http://blog.csdn.net/v5zsq/article/details/61428924

    Description 
    n个小木条,一段前面有一个小箭头,给出第一个小木条的非箭头端端点横坐标以及每个小木条箭头端的坐标,现在要从下往上把这n’个木条按顺序叠放好,要求相邻两个小木条必须有一个共同端点且有交叠部分,问小木条有多少种放法 
    Input 
    第一行一整数n表示木条数量,之后输入n+1个整数分别表示第一个小木条非箭头端点和n个小木条的箭头端点横坐标(1<=n < 2000,每个端点横坐标是一个介于1~n+1之间的整数,保证第一个小箭头朝右) 

    思路:

    定义dp(i,j)表示目前是第i个木头,他的区间是[min(j, a[i]), max(j, a[i])].

    然后我们判断一下a[i-1]的范围和这个区间的范围,即分类讨论五种。

    然后为了维护其中两种,所以我们这里还用了一个sum[j]数组表示dp[i][0]~dp[i][j]的和,然后这样就可以O(1)的到了

    注意特判n=1的时候(因为这个wa了一发)

    复杂度O(n^2)

    //看看会不会爆int!数组会不会少了一维!
    //取物问题一定要小心先手胜利的条件
    #include <bits/stdc++.h>
    using namespace std;
    #pragma comment(linker,"/STACK:102400000,102400000")
    #define LL long long
    #define ALL(a) a.begin(), a.end()
    #define pb push_back
    #define mk make_pair
    #define fi first
    #define se second
    #define haha printf("haha
    ")
    const int maxn = 2000 + 5;
    const LL mod = 2147483647;
    LL dp[maxn][maxn];
    LL sum[maxn];
    int a[maxn];
    int n;
    
    int main(){
        while(scanf("%d", &n) == 1){
            for (int i = 0; i <= n; i++){
                scanf("%d", a + i);
            }
            if (n == 1) {
                printf("1
    "); continue;
            }
            memset(dp, 0, sizeof(dp));
            memset(sum, 0, sizeof(sum));
            for (int i = 1; i <= n + 1; i++){
                if (i == a[0] || i == a[1]) sum[i] = dp[1][i] = 1;
                sum[i] = 1;
            }
            int len = n + 1;
            for (int i = 2; i <= n; i++){
                for (int j = 1; j <= len; j++){
                    if (j == a[i]) continue;
                    int lb = min(j, a[i]), rb = max(j, a[i]);
                    //printf("lb = %d rb = %d
    ", lb, rb);
                    if (a[i - 1] < lb){
                        dp[i][j] += dp[i - 1][rb];
                    }
                    else if (a[i - 1] == lb){
                        dp[i][j] += (sum[len] - sum[lb] + mod) % mod;
                    }
                    else if (a[i - 1] > rb){
                        dp[i][j] += dp[i - 1][lb];
                    }
                    else if (a[i - 1] == rb){
                        dp[i][j] += sum[rb - 1];
                    }
                    else {
                        dp[i][j] += dp[i - 1][lb] + dp[i - 1][rb];
                    }
                    if (dp[i][j] >= mod) dp[i][j] %= mod;
                    //printf("dp[%d][%d] = %lld
    ", i, j, dp[i][j]);
                }
                for (int j = 1; j <= len; j++){
                    sum[j] = (sum[j - 1] + dp[i][j]) % mod;
                }
            }
            LL ans = 0;
            for (int i = 1; i <= len; i++){
                ans = (ans + dp[n][i]) % mod;
            }
            cout << ans << endl;
        }
        return 0;
    }
    View Code
  • 相关阅读:
    ABP文档
    SqlServer英文单词全字匹配
    npm不是以管理身份运行遇到的问题
    concurrenthashmap jdk1.8
    HashSet源码分析 jdk1.6
    Iterator设计模式--jdk1.7
    代理模式
    高并发下的HashMap,ConcurrentHashMap
    HashMap源码分析jdk1.6
    Stack&Vector源码分析 jdk1.6
  • 原文地址:https://www.cnblogs.com/heimao5027/p/6731165.html
Copyright © 2011-2022 走看看