# 596 라운드 Codeforces이 (사업부. 2, Technocup 2020 제거 2 라운드 기준) E. 록 푸시 DP인가

E. 락 푸시인가

당신은 m 미로 ×는 n의 왼쪽 위 셀 (1,1)에 있습니다. 당신의 목표는 오른쪽 아래 셀 (N, m)에 도착하는 것입니다. 당신은 오른쪽 또는 단계 당 아래, 하나의 셀 이동할 수 있습니다. 아래로 이동하면, 셀 (X + 1, Y)로 이동하면서 오른쪽 셀 (X, Y)로 이동하면, 셀 (X, Y + 1)로 이동합니다.

미로의 일부 세포는 바위가 포함되어 있습니다. 당신은 바위와 셀에 이동하면 바위는 당신이 이동하고있는 방향의 다음 셀에 푸시됩니다. 다음 셀이 바위가 포함되어있는 경우, 그렇게에 대한 자세한 기선을 제압 당했지만,됩니다.

미로는 꿰 뚫을 수없는 벽으로 미로가 불법의 밖에서 또는 바위를 둘 것, 따라서 어떤 움직임을 둘러싸여 있습니다.

(109) + (7) 모듈로 당신이 목표에 처음부터 취할 수있는 다른 법적 경로의 수를 계산합니다. 하나 개의 경로에 방문하지만, 다른에 방문하지 적어도 하나 개의 셀이있는 경우 두 경로가 서로 다른 것으로 간주됩니다.

입력

첫 번째 라인은 m, n은 정수 두 포함 - 미로 (1≤n, m≤2000)의 치수.

다음 N 라인은 미로를 설명한다. 이 라인은 각각 m 문자가 포함되어 있습니다. 이 라인의 제 i의 j 번째 문자가 셀 (i, j)가 암석을 포함하거나, 경우에 "R"동일하다 "." 전지 (I, J)이 비어있는 경우.

시작 셀 (1,1)이 비어 있음을 보장한다.

산출

(N, m) 모듈로 109 + 7 (1,1)는 다른 법적 경로의 수 - 하나의 정수를 출력한다.

입력
1
.
출력
1
입력
2 3
...
..R
출력
0
입력
(4) (4)
... R
.RR.
.RR.
R ...
출력
(4)

노트

첫 번째 샘플의 경우, 우리는 할 수 없습니다 (그리고 필요가 없습니다) 따라서 유일한 경로가 단일 셀 (1,1)으로 구성되어 이동.

두 번째 샘플의 경우 목표는 차단과 연결할 수있다.

세 번째 샘플 케이스에 대한 그림은 여기에서 찾을 수 있습니다 : https://subdomain.codeforc.es/menci/assets/rounds/1225/index.html

문제의 의미

없음 *의 m 행렬 상자 더미가, 당신은 창고지기가 연속 박스 당신이 밀어 수 있습니다.

(N, m은) 얼마나 많은 서로 다른 경로 프로그램의 번호가에 (1,1)에서 부탁드립니다.

문제 해결

정의 :
DP [I] [J] [0] (I, J)를 나타내는 프로그램 번호의 끝에 도달 할 내려가.
DP는 [I] [J]를 [ 1] 프로그램의 수는 거리 (I, J)에서 오른쪽 끝에 도달 나타낸다.

비교 명백
DP가 [내가] [j]가 [ 0] DP를 = I + 1] [J] [1] + DP [I + 2] [J] [1] + ... + DP [I + X [J] [1] (I + X + 1, j는까지 ) 박스의 단부에 밀려, A는 창고지기 못해.

마찬가지로 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