• POJ 3670 Eating Together


    之前一直不过,最后的过的思路如下:

    dp[i][j]表示的含义是  到第i位,最高为j的子序列的最长长度。

    递推式:

    dp[i][1] = dp[i-1][1] + (a[i] == 1?1:0);
    dp[i][2] = max(dp[i][1], dp[i-1][2]) + (a[i]==2?1:0);
    dp[i][3] = max3(dp[i][1], dp[i][2], dp[i-1][3]) + (a[i]==3?1:0)

    高度为1的,最长只能为之前的,加上本身(如果本身是1则可加,否则不行)(1111_)

    高度为2的,为刚才算出的 高1序列最长 与 之前高2序列最长 的最大值 再视情况包含本身。(11111_   或者 11112_)

    高度为3类同。(11111_ 或者 1111222_ 或者 11112222333_)

    为什么要算高2时要算 第i位高1 而不是第i-1位呢? 因为。如果当i是1的时候,则dp[i][1]>dp[i-1][1], 同时,dp[i][1]也符合dp[i][2](只是要求最高为2, 不是一定要到2,所以序列111也可以包含在高2的序列内),所以应当选dp[i][1];

    那么代码是如何避免 高3 序列包含如 1232123 这样不合法的序列呢?

    注意到,每个状态只能选择合并较低状态,或者保持之前状态,或者包含与本状态相当的数(如高2状态只会包含2),所以比本状态小的数在之后是不会进入这个状态序列的。

    注意到,当a[i]=2时,原先的高1保持不变,包含a[i]这位的子序列的只可能 加上dp[i][1]后包含在 高2 的状态内。(也可能不包含a[i],情况就是dp[i-1][2]比较大)而高2状态中不可能继续包含1.

    同样,a[i]=3时,包含该位的子序列也就跳入了 高3 中,之后高3只可能继续包含3 而不可能包含1 2, 所以不会出现1231 或者 1232这样的情况,只可能是1233.

    ……还是没说清楚。。

    至于为什么是可行的……

      i位前高j子序列是什么样的对i位以后没影响。所以任意都可以,自然是选最长的。。。

    POJ 3670 Eating Together
    #include <cstdio>
    #include <cstring>
    #include <cstdlib>
    #define max(a,b) ((a)>(b)?(a):(b))
    #define max3(a, b, c) (max((max((a),(b))),(c)))
    
    int dp[30010][4];
    int a[30010], b[30010];
    int n;
    
    int cal(int a[]) {
        int i;
        dp[0][1] = a[0] == 1?1:0;
        dp[0][2] = dp[0][1] + a[0] == 2?1:0;
        dp[0][3] = (max(dp[0][1], dp[0][2])) + (a[0]==3?1:0);
    
        for (i = 1; i < n; i++) {
            dp[i][1] = dp[i-1][1] + (a[i] == 1?1:0);
            dp[i][2] = max(dp[i][1], dp[i-1][2]) + (a[i]==2?1:0);
            dp[i][3] = max3(dp[i][1], dp[i][2], dp[i-1][3]) + (a[i]==3?1:0);
        }
    
        int max = 0;
        for (i = 1; i <= 3; i++) {
            if (max < dp[n-1][i]) max = dp[n-1][i];
        }
        return max;
    }
    
    int main() {
        while (~scanf("%d", &n)) {
            int i;
            for (i = 0; i < n; i++) {
                scanf("%d", &a[i]);
                b[n-1-i] = a[i];
            }
            int max = cal(a);
            int temp = cal(b);
            if (max < temp) max = temp;
            printf("%d\n", n - max);
        }
        return 0;
    }
  • 相关阅读:
    hd2068错排+组合
    POJ 1061 青蛙的约会 扩展欧几里得
    POJ 2115 C Looooops扩展欧几里得
    扩展欧几里得算法
    欧拉函数模板
    高精度模板
    快速幂模板
    HDU 4445 Crazy Tank 高中物理知识忘得差不多了
    POJ 3087 Shuffle'm Up 模拟,看着不像搜索啊
    HDU 4452 Running Rabbits 模拟
  • 原文地址:https://www.cnblogs.com/shinecheng/p/3068724.html
Copyright © 2020-2023  润新知