No.86 TVザッピング(2) - yukicoder
- 一度だけ右に曲がる閉路を検出すればよいとこまではわかったが、それを普通に実装して TLE した。(計算量の落とし方がわからなかった。)
- 右にまがる地点をスタート地点にして、真っ直ぐか左にしかまがらないケースに限定して考えると、進めるときは真っ直ぐに進むしかないことに気づけたと思う。
- 考える条件を限定してやるととっかりがつかみやすいのかも。あと二歩くらい考察する癖をつけよう。
- 最初に cnt > 4*(N+M) なら return してやることで、計算量を大幅に減らせるのはすごいと思った。
- nd = (4+d+dd)%4 をうっかり nd = (d+dd)%4 と書いてしまってバグってしまっていた。
class TvZapping2 {
public:
void solve(void) {
int N,M;
cin>>N>>M;
int cnt = 0;
vector<string> A(N);
REP(i,N)
{
cin>>A[i];
REP(j,M) if (A[i][j] == '.')
++cnt;
}
if (cnt > 4*(N+M))
{
cout<<"NO"<<endl;
return;
}
const int dx[] = {-1,0,1,0};
const int dy[] = {0,1,0,-1};
int sx, sy;
function<bool(int,int,int,int)> search = [&](int x, int y, int d, int c) {
for (int dd = 0; dd >= -1; --dd)
{
int nd = (4+d+dd)%4;
int nx = x+dx[nd];
int ny = y+dy[nd];
if (nx < 0 || M <= nx || ny < 0 || N <= ny)
continue;
if (nx==sx && ny==sy)
{
if (cnt == c)
return true;
return false;
}
if (A[ny][nx] != '.')
continue;
A[ny][nx] = '@';
bool found = search(nx,ny,nd,c+1);
A[ny][nx] = '.';
if (found)
return true;
break;
}
return false;
};
REP(d, 4)
{
REP(y,N)
REP(x,M)
{
if (A[y][x] != '.')
continue;
sx = x;
sy = y;
A[sy][sx] = '@';
if (search(sx,sy,d,1))
{
cout<<"YES"<<endl;
return;
}
A[sy][sx] = '.';
}
}
cout<<"NO"<<endl;
}
};