結果
| 問題 |
No.340 雪の足跡
|
| コンテスト | |
| ユーザー |
startcpp
|
| 提出日時 | 2016-01-30 00:08:22 |
| 言語 | C++11(廃止可能性あり) (gcc 13.3.0) |
| 結果 |
WA
|
| 実行時間 | - |
| コード長 | 2,884 bytes |
| コンパイル時間 | 711 ms |
| コンパイル使用メモリ | 70,576 KB |
| 実行使用メモリ | 50,496 KB |
| 最終ジャッジ日時 | 2024-09-21 18:52:10 |
| 合計ジャッジ時間 | 6,094 ms |
|
ジャッジサーバーID (参考情報) |
judge5 / judge4 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | AC * 5 |
| other | AC * 20 WA * 5 RE * 7 |
ソースコード
//基本的には、縦横の累積和を使って通行可マス高速列挙と幅優先探索なのだが、実装時にh * wマスを2h * 2wマスに変換したほうが楽。
//2h * 2wマスにすれば、1回以上大人が訪れたマスがそのまま訪れることの出来るマスになる!!(行けない方向には0が埋まっているのだよ)
//m-m-m
//|
//m-m-m
// |
//m-m-m
//例えば、こういうケースを考える。このケースでは、左下マスから上に行ったり、右上マスから下に行ったりしないようにするのだが、
//2h * 2wマスにしておけば、(元データにおける)隣接マス間において、間のマスの訪れた回数が0⇔通行不可になるので処理が簡単。
//実装が本質だってはっきりわかんだね!(間に合わなかった)
//デバッグ文消し忘れるとか恥ずかしい
//
#include <iostream>
#include <queue>
#include <tuple>
using namespace std;
int w, h, n;
int m;
int by[1000], bx[1000];
int rx[2002][2002];
int ry[2002][2002];
int dp[2002][2002];
const int dy[4] = {1, 0, -1, 0};
const int dx[4] = {0, 1, 0, -1};
bool isRange(int r, int c){
return (r >= 0 && r < 2 * h && c >= 0 && c < 2 * w);
}
void init(){
for( int i = 0; i < 2002; i++ )
for( int j = 0; j < 2002; j++ )
dp[i][j] = 114514194;
}
void make(){
cin >> w >> h >> n;
for( int i = 0; i < n; i++ ){
cin >> m; m++;
for( int j = 0; j < m; j++ ){
int t;
cin >> t;
by[j] = t / w; by[j] *= 2;
bx[j] = t % w; bx[j] *= 2;
}
//同じ位置にたいして2度足しているが、通行回数を求めるわけではないので問題ない
for( int j = 1; j < m; j++ ){
if( by[j-1] == by[j] ){
//横方向への移動
rx[by[j-1]][min(bx[j-1], bx[j])]++;
rx[by[j-1]][max(bx[j-1], bx[j]) + 1]--;
} else {
//縦方向への移動
ry[min(by[j-1], by[j])][bx[j-1]]++;
ry[max(by[j-1], by[j]) + 1][bx[j-1]]--;
}
}
}
for( int i = 0; i < 2*h; i++ )
for( int j = 1; j < 2*w; j++ )
rx[i][j] += rx[i][j-1];
for( int j = 0; j < 2*w; j++ )
for( int i = 1; i < 2*h; i++ )
ry[i][j] += ry[i-1][j];
}
int bfs(){
typedef tuple<int, int, int> T; //コスト, y, x
queue<T> que;
if( ry[0][0] || rx[0][0] )
que.push(T(0, 0, 0));
while( !que.empty() ){
T now = que.front();
int dist = get<0>(now);
int y = get<1>(now);
int x = get<2>(now);
que.pop();
if( dp[y][x] <= dist )
continue;
dp[y][x] = dist;
for( int i = 0; i < 4; i++ ){
int ny = y + dy[i];
int nx = x + dx[i];
if( isRange(ny, nx) && (ry[ny][nx] || rx[ny][nx]) )
que.push(T(dist + 1, ny, nx));
}
}
if( dp[2*h-2][2*w-2] > 5 * h * w ) return -1;
return dp[2*h-2][2*w-2] / 2;
}
int main(){
init();
make();
int res = bfs();
if( res == -1 ) cout << "Odekakedekinai.." << endl;
else cout << res << endl;
return 0;
}
startcpp