公式

E - Climbing Silver 解説 by en_translator


We will perform a Dynamic Programming (DP) to solve this problem.
Consider performing a DP defined as \(dp[i][j] = \{1\) if Takahashi can advance to \((i,j)\), and \(0\) otherwise\(\}\).

Initialize as \(dp[i][j]=0\) for all \(i\) and \(j\).
Since \((i,C)\) is reachable for all \(i\), set \(dp[i][C]=1\).
Then, update the DP table as follows:

  • For \(i=N-1,N-2,\dots,1\), perform the following.
    • For \(j=1,2,\dots,N\), update \(dp[i][j]\) as follows.
      • If any of \(dp[i+1][j-1],dp[i+1][j],dp[i+1][j+1]\) is \(1\), cell \((i,j)\) is reachable if we ignore the wall-cell condition. We will only consider this case.
      • If \(dp[i][j]=1\) at this point, cell \((i,j)\) is already reachable, so no further investigation is needed.
      • If \((i,j)\) is an empty cell, it is reachable, so set \(dp[i][j]=1\).
      • If \((i,j)\) is a wall cell, if cell \((k,j)\) is an empty cell for all \(i < k \le N\), then \((i,j)\) and all cells above in the \(j\)-th column are reachable, so set \(dp[k][j]=1\) for all \(1 \le k \le i\). Whether the condition holds can be examined by precomputing the lowermost wall cell in each \(j\)-th row.

This solution runs in \(O(N^2)\) time.

Sample code (C++):

#include<bits/stdc++.h>

using namespace std;

int main(){
  int t;
  cin >> t;
  while(t--){
    int n,c;
    cin >> n >> c;
    c--;
    vector<string> s(n);
    vector<int> low(n,-1);
    for(int i=0;i<n;i++){
      cin >> s[i];
      for(int j=0;j<n;j++){
        if(s[i][j]=='#'){ low[j]=i; }
      }
    }
    vector<vector<int>> dp(n,vector<int>(n,0));
    for(int i=0;i<n;i++){dp[i][c]=1;}
    for(int i=n-2;i>=0;i--){
      for(int j=0;j<n;j++){
        if(dp[i][j]>0){continue;}
        bool ok=false;
        if(dp[i+1][j]>0){ok=true;}
        if(j>0 && dp[i+1][j-1]>0){ok=true;}
        if(j+1<n && dp[i+1][j+1]>0){ok=true;}
        if(ok){
          if(s[i][j]=='.'){
            dp[i][j]=1;
          }
          else{
            if(low[j]==i){
              for(int k=0;k<=i;k++){
                dp[k][j]=1;
              }
            }
          }
        }
      }
    }
    for(auto &nx : dp[0]){cout << nx;}
    cout << "\n";
  }
  return 0;
}

投稿日時:
最終更新: