AtCoderグランドコンテスト031(AGC031)F - 順列と最小動的計画

オリジナルリンクwww.cnblogs.com/zhouzhendong/p/AGC031F.html

問題への性急な解決策

各隣接する二つの位置については、それらを置きます。

二つの隣接する位置にかかわらず、値を決定している場合。

そして、これらの番号のすべてのアウトは、2つのカテゴリに分かれ、一つのカテゴリーは、一つが満たされている、満たされていません。

DP激しくすることができます。任意の順序の不在下で充填することができるので、最終的に、階乗を掛けました。

コード

#include <bits/stdc++.h>
#define clr(x) memset(x,0,sizeof x)
#define For(i,a,b) for (int i=(a);i<=(b);i++)
#define Fod(i,b,a) for (int i=(b);i>=(a);i--)
#define fi first
#define se second
#define pb(x) push_back(x)
#define mp(x,y) make_pair(x,y)
#define outval(x) cerr<<#x" = "<<x<<endl
#define outtag(x) cerr<<"---------------"#x"---------------"<<endl
#define outarr(a,L,R) cerr<<#a"["<<L<<".."<<R<<"] = ";\
                        For(_x,L,R)cerr<<a[_x]<<" ";cerr<<endl;
using namespace std;
typedef long long LL;
typedef vector <int> vi;
LL read(){
    LL x=0,f=0;
    char ch=getchar();
    while (!isdigit(ch))
        f|=ch=='-',ch=getchar();
    while (isdigit(ch))
        x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
    return f?-x:x;
}
const int N=305*2,mod=1e9+7;
int Pow(int x,int y){
    int ans=1;
    for (;y;y>>=1,x=(LL)x*x%mod)
        if (y&1)
            ans=(LL)ans*x%mod;
    return ans;
}
void Add(int &x,int y){
    if ((x+=y)>=mod)
        x-=mod;
}
void Del(int &x,int y){
    if ((x-=y)<0)
        x+=mod;
}
int Add(int x){
    return x>=mod?x-mod:x;
}
int Del(int x){
    return x<0?x+mod:x;
}
int n;
int a[N],b[N];
int cnt=0,tot=0;
int dp[N][N][N];
vector <int> v;
int main(){
    n=read();
    For(i,1,n*2){
        a[i]=read();
        if (a[i]!=-1)
            b[a[i]]=1;
    }
    For(i,1,n){
        if (a[i*2-1]==-1&&a[i*2]==-1)
            cnt++,tot+=2;
        else if (a[i*2-1]==-1)
            tot+=2,v.pb(a[i*2]);
        else if (a[i*2]==-1)
            tot+=2,v.pb(a[i*2-1]);
    }
    For(i,1,n*2)
        if (!b[i])
            v.pb(i);
    sort(v.begin(),v.end());
    v.pb(0);
    reverse(v.begin(),v.end());
    dp[0][0][0]=1;
    For(i,1,tot)
        For(j,0,tot)
            For(k,0,tot){
                int val=dp[i-1][j][k];
                if (!val)
                    continue;
                if (!b[v[i]]){
                    Add(dp[i][j+1][k],val);
                    if (j>0)
                        Add(dp[i][j-1][k],val);
                    if (k>0)
                        Add(dp[i][j][k-1],(LL)val*k%mod);
                }
                else {
                    Add(dp[i][j][k+1],val);
                    if (j>0)
                        Add(dp[i][j-1][k],val);
                }
            }
    int ans=dp[tot][0][0];
    For(i,1,cnt)
        ans=(LL)ans*i%mod;
    cout<<ans<<endl;
    return 0;
}

おすすめ

転載: www.cnblogs.com/zhouzhendong/p/AGC031F.html