【THUPC 2018]ボート

問題

説明

ラベンダー、Caryophyllus、ジャスミン、ナデシコは現在、「ボート」ゲームという男をプレイ。

ゲームのルールはこれです:

  1. プレイヤーはときに、他の人が時にスカウト、男のボートを2つのチームのキャプテンを形成するのは自由です。
  2. ゲームが起動するたびに、両側は、マップがマトリックス01の形で表現され、システム生成のマップを持って1通行障害物を表し、0開放水域を発現し、通過することができます。
  3. 最初のラウンド、ローイングキャプテンの両側には、出発点のみに、つまり、障害物ではないが、出発点として、地図上で指定されなければなりません0
  4. 各ラウンドでは、船長は自分の漕ぎのみ四の方向に移動させることができるモバイルユニット、から四方の開放水域の上/下/左/右方向を指示することができます1 0(もちろん、マップの外に移動することはできません)に、操作が完了した後、あなたは、互いにターンの方向に移動するために自分自身を伝える必要があります
  5. 互いにボートラウンドごとに記録し、責任を推測し、他の可能な位置を漕ぐための責任の両方スカウトの動きの方向、スカウトの当事者は、この時点で他のボートの正確な場所は、あなたが起動できると推測している場合、そのミサイル、勝利スカウトの一つ。

さて、ジャスミンは彼女がすべてのこの時間については、他のいくつかの可能な場所があることを確認したかった、いくつかの他のレースのパスを記録しました。彼女は、計算では非常に良好ではなかったので、あなたへのこのタスクので。

入力形式

最初の行の入力は、3つの正の整数含ま\(\ N-)、\ (m個\)、\ (K \) それぞれのマップ(\ N-)\ OK \(m個\)このゲームがされている、列を\ (K \)ラウンド。

第二のラインに入力\(N + 1 \)が作用する\(N- \) OK \(m個\) 任意の区切り文字なしの01列の行列、特定の情報を示す地図、上に示した特定の意味を。

入力の長さの最後の行\(K \)文字列\(S \) 文字のみwasdの背面に構成するフロント\(Iは\)文字\(S_I \)は、各他を表します\(I \)ホイール、他のアップ漕ぎ/左/下/右に移動する単位距離。

出力フォーマット

出力ライン最初表す正の整数\(K \)相手が位置を漕ぎかもしれないいくつかのラウンドのゲームラウンドを。全ての入力データについて、正当な解決策があることを確認します

サンプル

入力

5 6 5
000000
001001
000100
001000
000001
dwdaa

出力

4

説明

入力のための説明

path.png

図は、パスの後に配列の視覚化の結果を示し、このときの他方の側の図は、青色漕ぎ可能な位置で示されています。

location.png

範囲

\(2 \ nは1500 \ M、1 \ K \ 5 \ 6回10 ^ \)

アルゴリズム

\(FFT \)

メンタリティー

ルーチン質問。

我々は、それが行列として表現され、パスの可視化を歩いていきます。行列です\(1 \)の位置が逆に取得していない、ウォークスルー表していました。

だから、この質問は、行列、行列の左上隅が、この時点に整列された後に会い、私たちが見つけることができるポイント数に相当します\(1 \)の元で\(1 \)は一致しません。

まで充填行列の列数考える(m個\)\カラム、次いで元の行列は一次元アレイに分割されている\(F、G \) すなわち、第二列に接続された第一列、第二列の後ろにこの背後に接続された第3のライン。

マトリックスは、次にアウト除去する\(G \)与える反転アレイ\を(G「\) および\(F \)の畳み込みのための\(F. \)

場合\(F \)の長さ\(\)は、\ (G \)の長さ\は、(B \) 困難ではない見つけるための要件を満たすために、マトリックスは、元画像と正規の左上隅に位置合わせすることができますポイント\((X、Y)\)その場合\(F \) 対応するセクションで\(Iは\)位置、マトリックス\((0,0)\)\(G \)に対応\ (0 \)\(G「\)に対応\(1-B \) 次いでする\((X、Y)\ ) 結果と行列の左上隅は、積層中に存在するであろう\(F. \)セクション\(私はB-1 \は+ ) で。

私たちは、この行列のポイント、彼らは統計として左上隅スタックするのに十分なスペースがあり、合法的にしたものにのみ必要(F \)\対応する結果には。

答えは、これらの結果です\(0 \)番号。

コード

#include <cmath>
#include <cstdio>
#include <iostream>
using namespace std;
#define LL long long
#define go(x, i, v) for (int i = hd[x], v = to[i]; i; v = to[i = nx[i]])
#define inline __inline__ __attribute__((always_inline))
LL read() {
  long long x = 0, w = 1;
  char ch = getchar();
  while (!isdigit(ch)) w = ch == '-' ? -1 : 1, ch = getchar();
  while (isdigit(ch)) {
    x = (x << 3) + (x << 1) + ch - '0';
    ch = getchar();
  }
  return x * w;
}
const int Max_n = 1505, Max_l = 5e6 + 5, mod = 998244353, G = 3;
int n, m, K, ans, dx[5] = {0, -1, 1, 0, 0}, dy[5] = {0, 0, 0, -1, 1};
int lim, bit, rev[Max_l], f[Max_l], g[Max_l];
int s[Max_l], a[Max_n][Max_n];
char S[Max_l];
int ksm(int a, int b) {
  int res = 1;
  for (; b; b >>= 1, a = 1ll * a * a % mod)
    if (b & 1) res = 1ll * res * a % mod;
  return res;
}
namespace NTT {
void dft(int *f, bool t) {
  for (int i = 0; i < lim; i++)
    if (rev[i] > i) swap(f[i], f[rev[i]]);
  for (int len = 1; len < lim; len <<= 1) {
    int Wn = ksm(G, (mod - 1) / (len << 1));
    if (!t) Wn = ksm(Wn, mod - 2);
    for (int i = 0; i < lim; i += len << 1) {
      int Wnk = 1;
      for (int k = i; k < i + len; k++, Wnk = 1ll * Wnk * Wn % mod) {
        int x = f[k], y = 1ll * Wnk * f[k + len] % mod;
        f[k] = (x + y) % mod, f[k + len] = (x - y + mod) % mod;
      }
    }
  }
}
}  // namespace NTT
void ntt(int *f, int *g) {
  NTT::dft(f, 0), NTT::dft(g, 0);
  for (int i = 0; i < lim; i++) f[i] = 1ll * f[i] * g[i] % mod;
  NTT::dft(f, 1);
  int Inv = ksm(lim, mod - 2);
  for (int i = 0; i < lim; i++) f[i] = 1ll * f[i] * Inv % mod;
}
int main() {
#ifndef ONLINE_JUDGE
  freopen("5447.in", "r", stdin);
  freopen("5447.out", "w", stdout);
#endif
  n = read(), m = read(), K = read();
  for (int i = 0; i < n; i++) {
    scanf("%s", S);
    for (int j = 0; j < m; j++) f[i * m + j] = S[j] == '1';
  }
  scanf("%s", S + 1);
  for (int i = 1; i <= K; i++) {
    if (S[i] == 'w') s[i] = 1;
    if (S[i] == 's') s[i] = 2;
    if (S[i] == 'a') s[i] = 3;
    if (S[i] == 'd') s[i] = 4;
  }
  int sx = 0, sy = 0, l = 0, r = 0, u = 0, d = 0;
  for (int i = 1; i <= K; i++) {
    sx += dx[s[i]], sy += dy[s[i]];
    l = min(l, sy), r = max(r, sy), u = min(u, sx), d = max(d, sx);
  }
  r -= l, sy = -l, l = 0, d -= u, sx = -u, u = 0;
  a[sx][sy] = 1;
  for (int i = 1; i <= K; i++) a[sx += dx[s[i]]][sy += dy[s[i]]] = 1;
  for (int i = 0; i <= d; i++)
    for (int j = 0; j < m; j++) g[i * m + j] = a[i][j] == 1;
  for (int i = 0; i < (d + 1) * m / 2; i++) swap(g[i], g[(d + 1) * m - i - 1]);
  bit = log2(n * m + (d + 1) * m) + 1, lim = 1 << bit;
  for (int i = 0; i < lim; i++)
    rev[i] = rev[i >> 1] >> 1 | ((i & 1) << (bit - 1));
  ntt(f, g);
  for (int i = 0; i < n - d; i++)
    for (int j = 0; j < m - r; j++) ans += !f[(d + i + 1) * m + j - 1];
  cout << ans;
}

おすすめ

転載: www.cnblogs.com/luoshuitianyi/p/11487415.html