首页 > 其他 > 详细

线性dp——hdu6578经典dp

时间:2019-08-10 00:57:13      阅读:96      评论:0      收藏:0      [点我收藏+]

 多校第一场第一题,这种类型的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<<\n;
    }
}

 

线性dp——hdu6578经典dp

原文:https://www.cnblogs.com/zsben991126/p/11330169.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!