Problem:
Problem F: Line Puzzle

プログラミングでパズルを解いてみよう。

n × n の数字が格子状に並んでいる。数字のいくつかは丸で囲まれており、これらを起点と呼ぶことにする。パズルのルールは以下のとおりである：

各起点から縦・横に進む１本の線を引く（斜めには引けない）。

通った数字の和が起点の数字と同じになるように線を伸ばす。

線は枝分かれしてはいけない。

線はすでに引かれた数字を通ることはできない（線は交差してはいけない）。

線は２個以上の起点を通ることはできない。

下図に示すように、パズルのゴールはすべての起点を使い、すべての数字に線を引くことである。

あなたの仕事は、パズルを解くプログラムを作成することである。
ただしこの問題では、与えられたパズルが解けるものかどうかを判定するだけでよい。

Input

入力は複数のデータセットからなる。各データセットの形式は以下のとおりである：

n
n × n の数字

n × n の数字が与えられるパズルを示し、起点の数字は負の数として与えられる。

n が 0 のとき入力の終わりを示す。

n は 3 以上 8 以下、起点以外の数字は 1 以上 50 以下、起点は -50 以上 -1 以下であると仮定してよい。また、入力されるパズルの性質として以下のことを仮定してよい：

与えられるパズルの各行、各列には最低でも１つの起点がある。

起点の個数は、全体の数字の個数 (n × n) の 20 % から 40 % 程度である。

Output

各データセットに対して、パズルが解けるものであれば "YES" を、そうでなければ "NO" と１行に出力せよ。

Sample Input

3
-3 1 1
2 -4 1
2 1 -1
3
-4 1 1
1 1 -6
1 -5 3
4
-8 6 -2 1
2 -7 -2 1
1 -1 1 1
1 1 1 -5
6
2 2 3 -7 3 2
1 -10 1 1 3 2
2 6 5 2 -6 1
3 4 -23 2 2 5
3 3 -6 2 3 7
-7 2 3 2 -5 -13
6
2 2 3 -7 3 2
1 -10 1 1 3 2
2 6 5 2 -6 1
3 4 -23 2 2 5
3 3 -6 2 3 7
-7 2 3 2 -5 -12
0

Output for the Sample Input

YES
NO
NO
YES
NO

Solution in C++ (judge verdict: Time Limit Exceeded)

#include <iostream>
#include <vector>

using namespace std;

int dx[] = { 1, -1, 0, 0 };
int dy[] = { 0, 0, 1, -1 };
int field[8][8] = { { 0 } };
bool used[8][8] = { { false } };
vector<int> startX, startY;

bool dfs(int n, int x, int y, int r, int k){
	if(r == 0){
		if(k == startX.size()){ return true; }
		x = startX[k];
		y = startY[k];
		++k;
	}else if(used[y][x] || field[y][x] < 0){
		return false;
	}
	r -= field[y][x];
	if(r < 0){ return false; }
	used[y][x] = true;
	for(int i = 0; i < 4; ++i){
		int nx = x + dx[i], ny = y + dy[i];
		if(x >= 0 && x < n && y >= 0 && y < n){
			if(dfs(n, nx, ny, r, k)){ return true; }
		}
	}
	used[y][x] = false;
	return false;
}

int main(){
	while(true){
		int n;
		cin >> n;
		if(n == 0){ break; }
		int sum = 0;
		for(int i = 0; i < n; ++i){
			for(int j = 0; j < n; ++j){
				cin >> field[i][j];
				sum += field[i][j];
				if(field[i][j] < 0){
					startX.push_back(j);
					startY.push_back(i);
				}
				used[i][j] = false;
			}
		}
		cout << (sum == 0 && dfs(n, 0, 0, 0, 0) ? "YES" : "NO") << endl;
		startX.clear();
		startY.clear();
	}
	return 0;
}