zoukankan      html  css  js  c++  java
  • 战胜序列 [性质dp]

    战胜序列



    color{red}{正解部分}

    F[i,a,b,c]F[i, a, b, c] 表示前 ii 项 , 分别以 0,1,20,1,2 为结尾的 最长战胜序列 长度为 a,b,ca, b, c 的方案数,
    枚举状态, O(3)O(3) 转移, 总复杂度 O(N4)O(N^4) .

    可以发现 00 结尾的 最长上升序列 去掉 00 后得到长度为 b1b-1 的以 22 序列结尾的序列,
    ba1b geq a-1, 同理 cb1c geq b-1, ac1a geq c-1 ,可得 ba2|b-a| le 2, ca2|c-a| le 2 .

    于是设 F[i,a,b,c]F[i, a, b, c] 表示前 ii 项, 分别以 0,1,20,1,2 为结尾的 最长战胜序列 长度为 a,a+b2,a+c2a, a+b-2, a+c-2 的方案数, 转移即可, 时间复杂度 O(N2)O(N^2) .


    color{red}{实现部分}

    使用状态去更新状态, 注意在 aa 变化时, b,cb,c 也要随着变化 .

    #include<bits/stdc++.h>
    #define reg register
    
    const int maxn = 2005;
    const int mod = 998244353;
    
    int read(){
            char c;
            int s = 0, flag = 1;
            while((c=getchar()) && !isdigit(c))
                    if(c == '-'){ c = getchar(), flag = -1; break ; }
            while(isdigit(c)) s = s*10 + c-'0', c = getchar();
            return s * flag;
    }
    
    int N;
    int Ans[maxn];
    int F[maxn][maxn][5][5];
    
    bool vis[maxn][3];
    
    char Smp[5];
    
    int main(){
            N = read();
            for(reg int i = 1; i <= N; i ++){
                    scanf("%s", Smp);
                    int len = strlen(Smp);
                    for(reg int j = 0; j < len; j ++) vis[i][Smp[j]-'0'] = 1;
            }
            F[0][0][2][2] = 1;
            for(reg int i = 0; i < N; i ++)
                    for(reg int j = 0; j <= i; j ++)
                            for(reg int a = 0; a <= 4; a ++)
                                    for(reg int b = 0; b <= 4; b ++){
                                            if(j+a-2 < 0 || j+b-2 < 0 || !F[i][j][a][b]) continue ;
                                            int len_1 = j+a-2, len_2 = j+b-2;
                                            if(vis[i+1][0]){
                                                    int nl = std::max(j, len_2+1);
                                                    int &t = F[i+1][nl][len_1-nl+2][len_2-nl+2];
                                                    t = (t + F[i][j][a][b]) % mod;
                                            }
                                            if(vis[i+1][1]){
                                                    int nl = std::max(j+1, len_1);
                                                    int &t = F[i+1][j][nl-j+2][b];
                                                    t = (t + F[i][j][a][b]) % mod;
                                            }
                                            if(vis[i+1][2]){
                                                    int nl = std::max(len_2, len_1+1);
                                                    int &t = F[i+1][j][a][nl-j+2];
                                                    t = (t + F[i][j][a][b]) % mod;
                                            }
                                    }
            for(reg int i = 0; i <= N; i ++)
                    for(reg int a = 0; a <= 4; a ++)
                            for(reg int b = 0; b <= 4; b ++){
                                    int t = std::max(i, std::max(i+a-2, i+b-2));
                                    printf("%d
    ", F[N][i][a][b]);
                                    Ans[t] = (Ans[t] + F[N][i][a][b]) % mod;
                            }
            for(reg int i = 1; i <= N; i ++) printf("%d ", Ans[i]);
            return 0;
    }
    
  • 相关阅读:
    【转】WPF DataGridComboBoxColumn使用
    【转】CAD 二次开发--属性块 Block和BlockReference
    【转】【Revit】Revit二次开发——读取cad中的文字信息
    【转】【Centos】Linux(Centos7)下搭建SVN服务器
    现代php编程
    drone实践记录
    PHP拆分YAPI导出的swagjson文件
    pydantic验证器Validator
    利用notion打造读书追逐系统
    opencv马赛克python实现
  • 原文地址:https://www.cnblogs.com/zbr162/p/11822403.html
Copyright © 2011-2022 走看看