AOJ0091
問題:Blur
解法:DFS
適当にやると計算量とメモリが爆発しそうなので、無駄に枝をはやさないように気をつける。
左上から右下に向かう落としかたに限定して、行単位で全部消えない場合はそこで探索をうちやめる。
盤面のコピーはとらず1つの盤面を使い回す(再帰だとこれが簡単にできて良い)。
答えは順不同かつ1つ見つければ良いため、解が見つかった時点で答えを出力しながら戻れば良い。
再帰苦手だったが、時間かければこれくらいは自力で書けるようになった。
#include<iostream> #include<vector> #include<map> using namespace std; #define rep(i,n) for(int i=0; i<n; ++i) const int N = 10; int c,n; vector<vector<int> > F; int SS[] = {3, 3, 5}; int SC[] = {5, 9, 13}; int S[3][5][5] = { { {0, 1, 0, 0, 0}, {1, 1, 1, 0, 0}, {0, 1, 0, 0, 0}, {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0} }, { {1, 1, 1, 0, 0}, {1, 1, 1, 0, 0}, {1, 1, 1, 0, 0}, {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0} }, { {0, 0, 1, 0, 0}, {0, 1, 1, 1, 0}, {1, 1, 1, 1, 1}, {0, 1, 1, 1, 0}, {0, 0, 1, 0, 0} } }; bool is_inside(int x, int y){ return x >= 0 && y>= 0 && x<N && y<N; } bool fall(int x, int y, int size){ if(!(is_inside(x,y) and is_inside(x+SS[size]-1, y+SS[size]-1)))return false; rep(i,SS[size])rep(j,SS[size])if(!(F[y+i][x+j] >= S[size][i][j]))return false; rep(i,SS[size])rep(j,SS[size])F[y+i][x+j] -= S[size][i][j]; c -= SC[size]; return true; } void undo(int x, int y, int size){ rep(i,SS[size])rep(j,SS[size])F[y+i][x+j] += S[size][i][j]; c += SC[size]; } bool hasline(int y){ rep(x,N)if(F[y][x] >= 1)return true; return false; } bool is_clear(){ return c==0; } bool dfs(int x, int y, int depth){ if(is_clear()) return depth == 0; if(depth <=0)return false; if(!is_inside(0, y))return false; if(!hasline(y))return dfs(0, y+1, depth); for(int i=x; i<N; ++i)rep(s,3){ if(fall(i, y, s)){ if(dfs(i, y, depth-1)){ cout << i+SS[s]/2 << " " << y+SS[s]/2 << " " << s+1 << endl; return true; } undo(i, y, s); } } return false; } int main(){ cin >> n; F = vector<vector<int> >(N, vector<int>(N)); rep(i,N)rep(j,N){ cin >> F[i][j]; c += F[i][j]; } dfs(0,0,n); return 0; }