Problem:
Problem D: Smartphone Game

Problem

人気のスマフォゲームの一機能を実装してみよう。ゲームは以下の仕様に基づく。

5*5のマスに、5種類のブロックが設置されている。

それぞれの種類のブロックには得点が設定されている。

得点には、ブロックの得点の他に、ボーナス得点が設定されている。最初のボーナス得点は1である。

ブロックを任意に1つだけ決めて、最大で n 回まで上下左右に移動できる。移動先のブロックは移動元のブロックのあった場所に移動する。つまり、隣接したブロックを交換する事になる。

移動した後、同じ種類のブロックが縦3個以上又は横3個以上に並んだ場合、並んだブロックは全て消える。

消えるべきブロックが全て消えた後、あるブロックの下に別のブロックが存在しない場合、そのブロックは落下する。落下とは、あるブロックの１つ上に辿り着くまで下に移動する事をいう。ブロックが下に存在しない場合は一番下に移動する。

全てのブロックの落下後にボーナス得点が1だけ加算される。

その後にブロックが並んだ場合、さらに消え、落下する。

ブロックが消える時に、ブロック１つにつき「ブロックの得点*ボーナス得点」が自分の得点に加算される。

１回のプレイで得られる最大の点数を求めよ。

Input

入力は複数のデータセットからなる。

各データセットは以下で表される。

n
a11 .. a15
.
.
a51 .. a55
score1 .. score5

aijは1から5までの数字で、ブロックの種類を表す。

scoreiは i 種類目のブロック１つ分の得点を表す。

n = -1 の時、入力が終了する。

Constraints

入力は以下の条件を満たす。

0 ≤ n ≤ 5

1 ≤ aij ≤ 5

0 ≤ scorei ≤ 100

テストケースの数は 10 を超えない。

入力に含まれる値は全て整数である。

Output

各データセット毎に、答えを一行に出力しなさい。

Sample Input

0
1 1 1 5 5
5 5 5 5 5
5 5 1 5 5
5 1 1 1 5
5 5 5 5 5
0 0 0 0 1
2
1 2 3 4 5
2 3 4 5 5
2 3 4 5 5
3 4 5 5 1
5 4 3 2 1
100 99 98 97 96
5
1 2 3 4 5
2 3 4 5 1
1 2 3 4 5
5 4 3 2 1
1 2 3 4 5
99 79 31 23 56
-1

Sample Output

17
2040
926

Solution in C++11 (judge verdict: Wrong Answer)

#include <iostream>
#include <vector>
#include <algorithm>
#include <string>
#include <sstream>
#include <cstring>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <numeric>
#include <cctype>
#include <tuple>
#include <iterator>
#include <bitset>
#include <random>
#include <assert.h>
#include <unordered_map>
#include <array>
#include <ctime>

#ifdef _MSC_VER
#include <agents.h>
#endif

#define FOR(i, a, b) for(int i = (a); i < (int)(b); ++i)
#define rep(i, n) FOR(i, 0, n)
#define ALL(v) v.begin(), v.end()
#define REV(v) v.rbegin(), v.rend()
#define MEMSET(v, s) memset(v, s, sizeof(v))
#define X first
#define Y second
#define MP make_pair
#define umap unordered_map

using namespace std;

typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;
typedef pair<int, int> P;
typedef unsigned int uint;

const int N = 5;

int score[N];

pair<int, vector<vector<int>>> check(vector<vector<int>> v){
	auto nxt = v;
	rep(i, N) rep(j, N){
		int c = v[i][j];
		if (0 < i && i < N - 1 && v[i - 1][j] == c && c == v[i + 1][j]){
			for (int k = -1; k <= 1; ++k) nxt[i + k][j] = 0;
		}
		if (0 < j && j < N - 1 && v[i][j - 1] == c && c == v[i][j + 1]){
			for (int k = -1; k <= 1; ++k) nxt[i][j + k] = 0;
		}
	}
	int cnt = 0;
	rep(i, N) rep(j, N) if (!nxt[i][j] && v[i][j]) cnt += score[v[i][j]-1];

	return MP(cnt, nxt);
}

void down(vector<vector<int>> &v){
	for (int i = N - 2; i >= 0; --i) rep(j, N){
		int k = i;
		while (++k < N) if (!v[k][j]) swap(v[k][j], v[k - 1][j]);
	}
}

int simulate(vector<vector<int>> v){
	int res = 0, bonus = 1, x;
	while (1){
		tie(x, v) = check(v);
		if (!x) return res;
		res += bonus++*x;
		down(v);
	}
}

int dx[] = { 0, 1, 0, -1 };
int dy[] = { 1, 0, -1, 0 };
int dfs(int i, int j, int n, vector<vector<int>> &v){
	int res = simulate(v);
	if (n == 0) return res;
	rep(d, 4){
		int ni = i + dx[d], nj = j + dy[d];
		if (ni < 0 || ni >= N || nj < 0 || nj >= N) continue;
		swap(v[i][j], v[ni][nj]);
		res = max(res, dfs(ni, nj, n - 1, v));
		swap(v[i][j], v[ni][nj]);
	}
	return res;
}

int main(){
	ios::sync_with_stdio(false);

	auto v = vector<vector<int>>(N, vector<int>(N));

	int n;
	while (cin >> n, ~n){
		rep(i, N) rep(j, N) cin >> v[i][j];
		rep(i, N) cin >> score[i];
		int ans = 0;
		rep(i, N) rep(j, N) ans = max(ans, dfs(i, j, n, v));
		cout << ans << endl;
	}


	return 0;
}