程序锁 - dp

题目大意:
给你两个字符串,每个位置是P,V,?之一。P表示-1,V表示+1,?表示不确定。
问有多少将?替换成P或V的方案,使得下述算法不会gg:
维护两个指针(一开始在最开头)和当前和s。
若两个指针都在末尾,结束。
若其中一个指针已经在末尾,移动另一个。
若当前和s<0,随意移动一个。
若否则从下一个为V的指针中随意选一个,若不存在则随意选一个。
s初始为0,且每次指针移动s就+=对应位置。
若存在一种移动方式使得某时刻s<0则gg。
n,m<=5000。
题解:
考虑给定一个序列不会gg的充要条件。
对每个序列求一个以-1为下一个或整个序列(即下一个位置是空)的最小前缀。
若两个最小前缀的下一个都是空,则需要使得这两个最小前缀和大于等于0;否则要二者的和大于等于1。(亦即存在一种移动方式,几乎能够取到两个最小前缀的和)
设dp[i,j,0/1]表示从i开始之后的前缀最小值是j的方案数即可。

#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define Rep(i,v) rep(i,0,(int)v.size()-1)
#define lint long long
#define mod 998244353
#define ull unsigned lint
#define db long double
#define pb push_back
#define mp make_pair
#define fir first
#define sec second
#define gc getchar()
#define debug(x) cerr<<#x<<"="<<x
#define sp <<" "
#define ln <<endl
using namespace std;
typedef pair<int,int> pii;
typedef set<int>::iterator sit;
inline int inn()
{
    int x,ch;while((ch=gc)<'0'||ch>'9');
    x=ch^'0';while((ch=gc)>='0'&&ch<='9')
        x=(x<<1)+(x<<3)+(ch^'0');return x;
}
const int N=5010;
int fv[2][2][N<<1],gv[2][2][N<<1];
#define F(a,b) fv[(a)&1][b+N]
#define G(a,b) gv[(a)&1][b+N]
inline int upd(int &x,int y) { return x+=y,(x>=mod?x-=mod:0); }
inline int getdp(char *s,int n,int fv[N][N<<1],int gv[N][N<<1])
{
    F(n+1,0)=1;
    for(int i=n+1;i>1;i--)
    {
        rep(j,i-n-2,n+2-i) F(i-1,j)=G(i-1,j)=0;
        rep(j,i-n-1,n+1-i)
        {
            if(s[i-1]!='P') upd(F(i-1,j+1),F(i,j)),upd(G(i-1,j+1),G(i,j));//'V' OR '?'
            if(s[i-1]!='V')//'P' OR '?'
            {
                if(j>0) upd(G(i-1,0),F(i,j)),upd(G(i-1,0),G(i,j));
                else upd(F(i-1,j-1),F(i,j)),upd(G(i-1,j-1),G(i,j));
            }
        }
    }
    return 0;
}
#define f(a,b) fv[a][1][b+N]
#define g(a,b) gv[a][1][b+N]
#define fs(a) fsv[a+N]
#define gs(a) gsv[a+N]
#define P(x) (x>=mod?x-=mod:0)
char s[N];int len[10];
int fsv[N<<1],gsv[N<<1];
int main()
{
    rep(i,0,1) scanf("%s",s+1),getdp(s,len[i]=(int)strlen(s+1),fv[i],gv[i]);
    int ans=0;for(int t=max(len[0],len[1]),i=t;i>=-t;i--) fs(i)=fs(i+1)+f(1,i),gs(i)=gs(i+1)+g(1,i),P(fs(i)),P(gs(i));
    rep(i,-len[0],len[0]) ans=(ans+(lint)f(0,i)*fs(-i)+(f(0,i)+g(0,i))*(lint)gs(-i+1)+(lint)g(0,i)*fs(-i+1))%mod;
    return !printf("%d\n",ans);
}

猜你喜欢

转载自blog.csdn.net/Mys_C_K/article/details/85384118
DP
DP?
今日推荐