SuperCon予選
やったこと
眺めているとすごく難しそう
まあ考えていると(0, 0)からDFSではいができることに気づく
実装する
自明に「今までの距離 + 現在地から原点までの最短距離 > n」が成り立つ時はアなので枝刈り
DFSはstackを使ったほうが速いらしい
これは罠で実装が出来なかった
inlineをつけると1.5倍ぐらい早くなった
原点の4近傍の点が障害物もしくはもう通った点で埋まっていれば戻ってこれないので枝刈り
ここらへんで高速化のアイデアが尽きる
少し考えると答えがm<= 2ぐらいまでなら埋め込めることに気づく
さらに考えると原点からの距離がn / 2以上の障害物は関係ないのでmの値を減らせる
答えを埋め込む
ここでバグりまくる
最終的に添え字の"[]"の位置が間違っていることに気づく
とりあえず m = 0, 1(0というのは答えに関係のある障害物が無い時)の答えを埋め込む
m = 2の時を埋め込む
死ぬほどつらいのでn = 20, m= 2の時に絞る
i7-6700が頑張る
3,40分で答えが出る
埋め込む
応募用紙を書く
提出する
テストケースの実行結果
Ans= 133662, time=19
ソースコード
#include "sc1.h" #include "stdio.h" #include <iostream> using namespace std; int dx[4] = {0,1,0,-1}; int dy[4] = {-1,0,1,0}; int ans = 0, cnt = 0, cnt1; int index2[20]; bool mas[100][100], flag[100][100]; const int offset = 50; int index[21][21] = // 2*10^6 以上あるので省略 inline void dfs(int x, int y, int l){ if(mas[51][50] && mas[49][50] && mas[50][49] && mas[50][51]) return; if(scN - l < abs(offset - x) + abs(offset - y)) return; mas[x][y] = true; for(int i = 0; i < 4; ++i){ int nx = x + dx[i]; int ny = y + dy[i]; if(!mas[nx][ny]) dfs(nx, ny, l + 1); if(l + 1 == scN && nx == 0 + offset && ny == 0 + offset) ++ans; } mas[x][y] = false; } int main(){ scInput(); for(int i = 0; i < 100; ++i) for(int j = 0; j < 100; ++j){ mas[i][j] = false; } for(int i = 0; i < scM; ++i){ if(abs(scB[0][i]) + abs(scB[1][i]) > scN / 2) continue; mas[scB[0][i] + offset][scB[1][i] + offset] = true; cnt1 = i; index2[cnt] = i; ++cnt; } if(cnt == 0){ scOutput(ans0[scN / 2 - 7]); return 0; } if(cnt == 1){ scOutput(ans1[scN / 2 - 7][index[scB[0][cnt1] + 10][scB[1][cnt1] + 10]]); return 0; } if(cnt == 2 && scN == 20){ int ax = scB[0][index2[0]], ay = scB[1][index2[0]]; int bx = scB[0][index2[1]], by = scB[1][index2[1]]; int a = index[ax + 10][ay + 10], b = index[bx + 10][by + 10]; if(a > b) swap(a, b); scOutput(ans20_2[a][b - a - 1]); return 0; } mas[offset][offset] = true; dfs(0 + offset, 0 + offset, 0); scOutput(ans); }
感想
正直定数倍高速化コンテスト感が強かった
チーム名はaldas(リパライン語で雷雲の意)です かっこいいね(@sashimiwiki さんに付けて頂きました ありがとうございます!)