This page looks best with JavaScript enabled

キーエンス プログラミング コンテスト 2021 C - Robot on Grid (diff: 1468)

 ·  ☕ 3 min read  ·  ✍️ reud · 👀... views

難しすぎませんか?

問題はココ: C - Robot on Grid

考えること

こういった問題は dp の遷移式をまず考えてみると良さげ。

座標(i,j)に到達する時のロボットの移動経路数$dp[i][j]$について考えてみる。

$$

dp[i][j] = dp[i-1][j] + dp[i][j-1]

$$

こういった遷移式は予想出来る。 これは全パネルについて

次に初期値をどう設定するかについて考える。

ただ、パネルの貼り方は$3^{HW-K}$通りあるのでその辺りは考慮する必要がある。

ここで$dp[i][j]$を文字の書き込み方の全パターンについてそれぞれの場合について(i,j)への移動経路の総和を998244353で割ったあまり

にすると、この問題の答えは$dp[H][W]$になります。

次に遷移式について考えてみる。

$$
dp[i+1][j] += \frac{2}{3}*dp[i][j]
$$

になる。ここで$\frac{2}{3}$は$dp[i][j]$、すなわち、文字の書き込み方の全パターンについて(i,j)への移動経路の総和であるので、
$dp[i][j]$の

  • $\frac{1}{3}$は$dp[i][j]$にRを貼った場合
  • $\frac{1}{3}$は$dp[i][j]$にDを貼った場合
  • $\frac{1}{3}$は$dp[i][j]$にXを貼った場合

ここで、右に行けるような場合について考えると、RXの場合について遷移出来る。よって、$\frac{2}{3} * dp[i][j]$になる。

下の場合も同様。よって、以下の様な遷移式を構築出来る。

  • 上も左もパネルが貼られていない時
dp[i][j] = \frac{2}{3} * dp[i-1][j] + \frac{2}{3} * dp[i][j-1]

ここで上が D なら全パターン遷移するし、上が R なら$dp[i-1][j]$からは遷移しないなど遷移式が周りのマスの様子によって細かく変わっていくことに注意する。

で、先述の通りパネルの貼り方は$3^{HW-K}$通りあるので$dp[1][1] = 3^{HW-K}$になる。

後は動的計画法で解けるので、計算量はO(HW)

こんな感じで解ける(dp を H+1,W+1)で持っとけば境界線チェックいらなくなるのでそうすればよかった・・・

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
#include <bits/stdc++.h>
#include <atcoder/all>
#define INF 1e9
#define INFLL 1ull<<60u
using namespace std;

#define REPR(i,n) for(int i=(n); i >= 0; --i)
#define FOR(i, m, n) for(int i = (m); i < (n); ++i)
#define REP(i, n) for(int i=0, i##_len=(n); i<i##_len; ++i)
#define ALL(a)  (a).begin(),(a).end()
#define endl "\n"

template<class T>bool chmin(T &a, const T &b) { if (b<a) { a=b; return true; } return false; }
template<class T>bool chmax(T &a, const T &b) { if (a<b) { a=b; return true; } return false; }
typedef long long ll;

using vi = vector<int>;
using vvi = vector<vi>;
using vpii = vector<pair<int,int>>;

using mi = atcoder::modint998244353;

void solve() {
    int H,W,K; cin >> H >> W >> K;
    // R,D,X 0,1,2
    vector<vector<mi>> dp(H,vector<mi>(W,0));
    vector<vector<char>> grid(H,vector<char>(W,'.'));

    REP(_,K) {
        int h,w;
        char c;
        cin >> h >> w >> c;

        h--; w--;
        grid[h][w] = c;
    }

    using Position = pair<int,int>;
    dp[0][0] = mi(3).pow(H*W - K);

    auto r = mi(2) * mi(3).inv();

    REP(h,H) REP(w,W) {
            if (grid[h][w] == 'D' && h + 1 < H) {
                dp[h+1][w] += dp[h][w];
                continue;
            } else if (grid[h][w] == 'R' && w + 1 < W) {
                dp[h][w+1] += dp[h][w];
                continue;
            } else if (grid[h][w] == 'X') {
                if(h + 1 < H) dp[h+1][w] += dp[h][w];
                if (w + 1 < W) dp[h][w+1] += dp[h][w];
                continue;
            } else if (grid[h][w] == '.') {
                if (h+1 < H) dp[h+1][w] += dp[h][w] * r;
                if (w+1 < W) dp[h][w+1] += dp[h][w] * r;

            }
        }

    cout << (dp[H-1][W-1]).val() << endl;

}

int main() {
    solve();
    return 0;
}

提出 #19488484 - キーエンス プログラミング コンテスト 2021

参考

Share on

reud
WRITTEN BY
reud
Stundent