zoukankan      html  css  js  c++  java
  • 线性dp——hdu6578经典dp

     多校第一场第一题,这种类型的dp之前做过两题,状态转移一般是从当前状态往后推的

    很经典的dp,不过很卡时间

    /*
    定义 dp[t][i][j][k]代表填完前 t 个位置后,{0, 1, 2, 3} 这 4 个数字最后一次出现的位置,
    排序后为 t, i, j, k(t > i > j > k) 的方案数目,则按照第 t 位的数字的四种选择,可以得
    到四种转移。
    t选t-1这个位置的数:dp[t][i][j][k]
    t选i这个位置的数:dp[t][t-1][j][k]
    t选j这个位置的数:dp[t][t-1][i][k]
    t选k这个位置的数:dp[t][t-1][i][j]
    枚举r[l]==t+1的所有条件,当且仅当满足所有条件时才进行转移 
    
    最后的方案数=sum{dp[n]} 
    总时间复杂度 O(n4)。滚动一维,空间复杂度 O(n3)
    */
    #include<bits/stdc++.h>
    using namespace std;
    #define maxn 110
    #define ll long long 
    #define mod 998244353
    ll dp[2][maxn][maxn][maxn];
    int n,m;
    struct Node{
        int l,x;
        Node(){}
        Node(int l,int x):l(l),x(x){}
    };
    vector<Node>v[maxn];
    
    inline void update(ll &a,ll b){
        a=(a+b);
        while(a>=mod)a-=mod; 
    }
    int c;
    void solve(){
        c=0;
        dp[c][0][0][0]=1;
        for(int t=1;t<=n;t++){
            c^=1;
            for(int i=0;i<=t;i++)
                for(int j=0;j<=i;j++)
                    for(int k=0;k<=j;k++)
                        dp[c][i][j][k]=0;
            
            for(int i=0;i<t;i++)
                for(int j=0;j<=i;j++)
                    for(int k=0;k<=j;k++){
                        update(dp[c][i][j][k],dp[c^1][i][j][k]);
                        update(dp[c][t-1][j][k],dp[c^1][i][j][k]); 
                        update(dp[c][t-1][i][k],dp[c^1][i][j][k]);
                        update(dp[c][t-1][i][j],dp[c^1][i][j][k]);
                    }
            for(int p=0;p<v[t].size();p++){//枚举每个条件 
                int l=v[t][p].l,x=v[t][p].x;
                for(int i=0;i<t;i++)
                    for(int j=0;j<=i;j++)
                        for(int k=0;k<=j;k++){
                            int cnt=1;
                            if(i>=l)cnt++;
                            if(j>=l)cnt++;
                            if(k>=l)cnt++;
                            if(cnt!=x)dp[c][i][j][k]=0;
                        }
            }
        }
    }
    
    int main(){
        //ios::sync_with_stdio(false);
        int t;cin>>t;
        while(t--){
            for(int i=0;i<maxn;i++)v[i].clear();
            
            scanf("%d%d",&n,&m);
            for(int i=1;i<=m;i++){
                int l,r,x;
                scanf("%d%d%d",&l,&r,&x);
                v[r].push_back(Node(l,x));
            }
            solve();
            ll ans=0;
            for(int i=0;i<n;i++)
                for(int j=0;j<=i;j++)
                    for(int k=0;k<=j;k++)
                        ans+=dp[c][i][j][k],ans%=mod;
            cout<<ans<<'
    ';
        }
    }
  • 相关阅读:
    Traceroute侦测主机到目的主机之间所经路由情况的重要工具
    TCP/IP详解之IP协议
    Hello world
    [LeetCode] 198. 打家劫舍
    [LeetCode] 191. 位1的个数
    [LeetCode] 190. 颠倒二进制位
    python里的排序
    [LeetCode] 189. 旋转数组
    [LeetCode]187. 重复的DNA序列
    [LeetCode] 179. 最大数
  • 原文地址:https://www.cnblogs.com/zsben991126/p/11330169.html
Copyright © 2011-2022 走看看