【ARC074E】RGB Sequence(神奇的dp)

注意到颜色的种类数只有 3 3 3 种, n ≤ 100 nleq 100 n100 也很小。

然后就有了一种神奇的 dp 状态:

考虑从前往后填方块,设 d p ( i , j , k ) dp(i,j,k) dp(i,j,k) 表示离当前位置最近的颜色位置在 i i i,离当前位置第二近的颜色位置在 j j j,离当前位置第三近的颜色位置在 k k k。显然,当前位置就是 i i i,所以这样设置帮我们减少了一维。

O ( n 2 m ) O(n^2m) O(n2m) 枚举每一个区间和每一个要求,预处理哪些方案是不合法的,然后直接 O ( n 3 ) O(n^3) O(n3) 进行 dp 即可。

代码如下:


#include<bits/stdc++.h>
 
#define N 310
#define mod 1000000007
 
using namespace std;
 
int n,m,ql[N],qr[N],x[N];
int dp[N][N][N];
 
void add(int &x,int y)
{
    if((x+=y)>=mod) x-=mod;
}
 
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=m;i++)
        scanf("%d%d%d",&ql[i],&qr[i],&x[i]);
    dp[1][0][0]=3;
    for(int i=1;i<=m;i++)
    {
        for(int j=0;j<qr[i];j++)
        {
            int t=max(0,j-1);
            for(int k=0;k<=t;k++)
            {
                if(x[i]==1&&ql[i]<=j) dp[qr[i]][j][k]=-1;
                if(x[i]==2&&(j<ql[i]||ql[i]<=k)) dp[qr[i]][j][k]=-1;
                if(x[i]==3&&k<ql[i]) dp[qr[i]][j][k]=-1;
            }
        }
    }
    for(int i=1;i<=n;i++)
    {
        for(int j=0;j<i;j++)
        {
            int t=max(0,j-1);
            for(int k=0;k<=t;k++)
            {
                if(dp[i][j][k]==-1) continue;
                if(dp[i+1][j][k]!=-1) add(dp[i+1][j][k],dp[i][j][k]);
                if(dp[i+1][i][j]!=-1) add(dp[i+1][i][j],dp[i][j][k]);
                if(dp[i+1][i][k]!=-1) add(dp[i+1][i][k],dp[i][j][k]);
            }
        }
    }
    int ans=0;
    for(int i=0;i<n;i++)
    {
        int t=max(0,i-1);
        for(int j=0;j<=t;j++)
            if(dp[n][i][j]!=-1) 
                add(ans,dp[n][i][j]);
    }
    printf("%d
",ans);
    return 0;
}
原文地址:https://www.cnblogs.com/ez-lcw/p/14448644.html