(Technocup 2020エリミネーションラウンド2に基づいてディビジョン2、)#596 E.ロックはDPを押しですラウンドCodeforces

E.ロックプッシュです

あなたは、mラビリンス×Nの左上のセル(1,1)です。あなたの目標は、右下のセル(N、M)を取得することです。あなただけの、ステップごとに1つのセルを右または下に移動することができます。下降するセル(X + 1、Y)が表示されますしながら右のセル(X、Y)から移動すると、セル(X、Y + 1)に移動します。

迷路のいくつかの細胞は岩が含まれています。あなたは岩とのセルに移動すると、岩はあなたが移動している方向の次のセルにプッシュされます。次のセルには岩が含まれている場合、それはそうで、さらにプッシュ、およびます。

迷路は、このように迷路の外に、あなたや任意の岩を置く任意の動きは違法である、不可解な壁に囲まれています。

109 + 7を法あなたはスタートからゴールまで取ることができますさまざまな法的パスの数をカウントします。1つのパスに訪れたが、他に訪問しない少なくとも1個のセルがある場合、2つのパスが異なると考えられています。

入力

ラビリンスの寸法(1≤n、m≤2000) - 最初の行は二つの整数N、Mを含有します。

次のn行は、ラビリンスを記述する。これらの線のそれぞれは、m個の文字が含まれています。これらの線のi番目のj番目の文字がセル(i、j)の場合、「R」に等しいロックが含まれているか、または「」セル(i、j)が空の場合。

開始セル(1,1)が空であることが保証されています。

出力

単一の整数印刷 - (M、N)を(1,1)とは異なる法的なパスの数を109 + 7を法。

入力
1 1

出力
1
入力
2 3
...
..R
出力
0
入力
4 4
... R
.RR。
.RR。
R ...
出力
4

注意

我々はできない(とする必要はありません)移動最初のサンプルの場合には、従って唯一のパスは、単一のセル(1,1)からなります。

第2のサンプルケースでの目標は、ブロックされ、到達不能です。

第三のサンプルケースのためのイラストはここで見つけることができます:https://subdomain.codeforc.es/menci/assets/rounds/1225/index.html

問題の意味

N * mの行列、箱の山があり、あなたは倉庫番は、連続ボックスあなたはプッシュすることができます。

(N、M)はどのように多くの異なるパスのプログラムの数を持っているから(1,1)からお願いします。

問題の解決策

定義された:
DP [I] [J] [0]プログラム番号の末尾に到達するためにダウンする(i、j)を表しています。
DP [I] [J] [ 1] プログラムの数が離れて(I、J)から右へ最後に到達表します。

比較明らか
DPは[i]を[j]が[ 0] DPを= [I + 1] [j] [1] + DP [I + 2] [J] [1] + ... + DP [I + X ] [J] [1]、(I + X + 1、jはまで ) ボックスの端部に押し込まれ、倉庫番ができません。

同様に、DP [I] [J] [1]それは本当です。

明らかに、このプレフィックスの後ろにしこりや、それを最適化することができ、その後、あなたがなることができ、N ^ DP 2がシフトしています。

コード

#include<bits/stdc++.h>
using namespace std;
const int maxn = 2005;
int n,m;
const int mod = 1e9+7;
char a[maxn][maxn];
// 0 for down;1 for right
int num[maxn][maxn][2],dp[maxn][maxn][2],sum[maxn][maxn][2];
int main(){
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++){
        scanf("%s",a[i]+1);
    }
    if(n==1&&m==1&&a[1][1]=='.'){
        cout<<"1"<<endl;
        return 0;
    }
    if(a[1][1]=='R'||a[n][m]=='R'){
        cout<<"0"<<endl;
        return 0;
    }
    for(int i=n;i>=1;i--){
        for(int j=m;j>=1;j--){
            if(a[i][j]=='R'){
                num[i][j][0]+=1;
                num[i][j][1]+=1;
            }
            num[i][j][0]+=num[i+1][j][0];
            num[i][j][1]+=num[i][j+1][1];
        }
    }
    dp[n][m][0]=1;dp[n][m][1]=1;sum[n][m][0]=1;sum[n][m][1]=1;
    for(int i=n;i>=1;i--){
        for(int j=m;j>=1;j--){
            if(i==n&&j==m)continue;
            dp[i][j][0]=(sum[i+1][j][0]-sum[n-num[i+1][j][0]+1][j][0])%mod;
            dp[i][j][1]=(sum[i][j+1][1]-sum[i][m-num[i][j+1][1]+1][1])%mod;
            sum[i][j][0]=(sum[i+1][j][0]+dp[i][j][1])%mod;
            sum[i][j][1]=(sum[i][j+1][1]+dp[i][j][0])%mod;
        }
    }
    cout<<(dp[1][1][0]+dp[1][1][1]+2ll*mod)%mod<<endl;
}

おすすめ

転載: www.cnblogs.com/qscqesze/p/11782207.html