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: Wrong Answer)

#include<iostream>
#include<vector>
#include<cstdio>

#define REP(i,n) for(int i=0; i<(int)(n); i++)

using namespace std;

typedef unsigned long long ull;

int n;
int b[10][10];
int id[10][10];
vector<vector<ull> > v;
int nid;

const int dx[4] = { 1,-1, 0, 0};
const int dy[4] = { 0, 0, 1,-1};

inline ull hash(int x, int y){
  return (((ull)1) << ((x-1) + (y-1)*8));
}

void check(int x, int y, int sum, ull f){
  if(sum == 0){
    v[nid].push_back(f);
    return;
  }
  REP(i,4){
    int xx = x+dx[i];
    int yy = y+dy[i];
    int s  = sum - b[yy][xx];
    if(s < 0 || b[yy][xx] < 0) continue;
    ull h  = hash(xx,yy);
    if((h & f) != 0) continue;
    check(xx,yy,s,(f|h));
  }
}

bool ans(int idx, ull f){
  if(idx == v.size()) return true;
  REP(i,v[idx].size()){
    if((f & v[idx][i]) == 0 && ans(idx+1, (f | v[idx][i])))
       return true;
  }
  return false;
}

int main(){
  REP(i,10) REP(j,10) b[i][j] = -1;
  while(scanf("%d",&n), n){
    int idx = 0;
    int sum = 0;

    REP(i,n) REP(j,n){
      int tmp;
      scanf("%d",&tmp); 
      b[i+1][j+1] = tmp;
      if(tmp < 0)
	id[i+1][j+1] = idx++;
      sum += tmp;
    }

    if(sum != 0){
      puts("NO");
      continue;
    }

    v.clear();
    v = vector<vector<ull> >(idx);

    for(int y=1; y<=n; y++){
      for(int x=1; x<=n; x++){
	if(b[y][x] < 0){
	  nid = id[y][x];
	  check(x,y,-b[y][x],hash(x,y));
	}
      }
    }

    puts(ans(0,0)?"YES":"NO");
  }
  return 0;
}