Problem:
会津の埋蔵金
会津には古くから伝わる埋蔵金の伝説があります。あなたは、遂に埋蔵金が埋まっている場所を突き止めました。埋蔵金が埋まっている深さ、掘り進める地層の状態が分かっているので、綿密に計画を立てれば最小費用で埋蔵金まで到達することができます。そこであなたは、地層の状態を読み取って埋蔵金の埋まっている深さまで最小費用で到達するルートを算出するプログラムを作成することにしました。
地層の状態は 2 次元格子状に配置されたセルで表わされ、各セルの位置は座標 (x,y) で表されます。左上を (1,1) とし、x 座標は右に行くにつれて大きくなり、y 座標は下に深くなるにつれて大きくなるものとします。あなたは y 座標の一番小さいセルのうち一つを選んでそこから掘り始め、y 座標の一番大きいセルの一つまで掘り進めます。地層には以下の 2 種類のセルがあります：
土の詰まったセル。掘るのに、セルごとに決められた費用がかかる。
酸素のたまったセル。掘る必要はなく、セルごとに決まった量の酸素を補給できる。一度酸素を補給したセルの酸素はなくなり、再度の補給はできない。また、このセルに辿りついたら必ず酸素の補給をしなければならない。
あるセルから掘ることができるのは左右と下方向のセルのみです。
一度掘ったセルを左右に移動することはできますが、上に移動することはできません。
発掘にあたっては、酸素ボンベを携帯しなければなりません。酸素ボンベの残量が 0 になった瞬間、移動も発掘も酸素の補給もできなくなります。残量はセルを移動するたびに 1 減ります。酸素ボンベの残量が 0 で埋蔵金の埋まっている深さまで到達しても、到達したとみなされません。また、酸素のたまったセルでは酸素を補給することができますが、容量を超えた分は廃棄されます。
地層のサイズ 、発掘費用、酸素ボンベの容量、初期状態で持っている酸素の量、地層の情報を入力とし、一番深いセルまでたどりつくための最小費用を出力するプログラムを作成してください。ただし、最小費用が発掘費用を超えてしまう場合や、どのように掘り進めても埋蔵金にたどりつけない場合は“NA”と出力してください。
Input
複数のデータセットの並びが入力として与えられる。入力の終わりはゼロふたつの行で示される。
各データセットは以下の形式で与えられる。
W
H
f
m
o
c
1,1
c
2,1
...
c
W,1
c
1,2
c
2,2
...
c
W,2
...
c
1,H
c
2,H
...
c
W,H
１行目に地層の横方向のサイズ
W
, 縦方向のサイズ
H
(3 ≤
W
,
H
≤ 10) が与えられる。 ２行目にあなたの発掘費用を表す整数
f
(1 ≤
f
≤ 10000)、酸素ボンベの容量を表す整数
m
(3 ≤
m
≤ 50)、初期状態で持っている酸素の量を表す整数
o
(o ≤
m
) が与えられる。
続く
H
行に地層の情報
c
i,j
が与えられる。
c
i,j
は、座標 (
i
,
j
) に対するセルの情報を表し、以下の形式で与えられる：
負の値の場合、土の詰まったセルで、値は費用を表す
正の値の場合、酸素のたまったセルで、値は酸素の量を表す
ただし、酸素のたまったセルは 50 箇所以内である。
データセットの数は50 を超えない。
Output
データセットごとに、最少費用または NA を1行に出力する。
Sample Input
3 3
100 10 10
-100 -20 -100
-100 -20 -100
-100 -20 -100
3 3
100 10 10
-100 -20 -100
-100 -20 -20
-100 -60 -20
3 3
100 10 3
-100 -20 -100
-20 -20 -20
-20 -100 -20
3 3
100 3 3
-100 -20 -30
-100 -20 2
-100 -20 -20
4 5
1500 5 4
-10 -380 -250 -250
-90 2 -80 8
-250 -130 -330 -120
-120 -40 -50 -20
-250 -10 -20 -150
0 0
Output for the Sample Input
60
80
NA
50
390

Submitted solutions:

code_snippet: #include <bits/stdc++.h>
using namespace std;

const int INF = 1012345678;

int solve(int H, int W, int F, int L, int O, const vector<vector<int> >& C) {
	L -= 1;
	O -= 1;
	if (O < 0) {
		return INF;
	}
	vector<vector<int> > dp(W, vector<int>(L + 1, INF));
	for (int i = 0; i < W; i++) {
		dp[i][O] = 0;
	}
	auto check = [&](int row, int oxy, int a, int b, int c, int d) -> pair<int, int> {
		// (row, a) -> (row, b) -> (row, c) -> (row, d)
		vector<bool> vis(W, false);
		oxy -= 1;
		if (oxy < 0) {
			return make_pair(-1, -1);
		}
		int cost = 0;
		auto update = [&](int pos) -> void {
			if (!vis[pos]) {
				vis[pos] = true;
				if (C[row][pos] < 0) {
					cost += -C[row][pos];
				}
				else {
					oxy = min(oxy + C[row][pos], L);
				}
			}
		};
		update(a);
		int cur = a;
		vector<int> targets = { b, c, d };
		for (int i : targets) {
			while (cur != i) {
				cur += (cur < i ? +1 : -1);
				oxy -= 1;
				if (oxy < 0) {
					return make_pair(-1, -1);
				}
				update(cur);
			}
		}
		return make_pair(oxy, cost);
	};
	for (int i = 0; i < H; i++) {
		vector<vector<int> > ndp(W, vector<int>(L + 1, INF));
		for (int j = 0; j <= L; j++) {
			for (int k = 0; k < W; k++) {
				if (dp[k][j] != INF) {
					for (int l = 0; l < W; l++) {
						for (int x = 0; x <= min(k, l); x++) {
							for (int y = max(k, l); y < W; y++) {
								pair<int, int> res1 = check(i, j, k, x, y, l);
								pair<int, int> res2 = check(i, j, k, y, x, l);
								if (res1.first != -1) {
									ndp[l][res1.first] = min(ndp[l][res1.first], dp[k][j] + res1.second);
								}
								if (res2.first != -1) {
									ndp[l][res2.first] = min(ndp[l][res2.first], dp[k][j] + res2.second);
								}
							}
						}
					}
				}
			}
		}
		dp = ndp;
	}
	int ans = INF;
	for (int i = 0; i < W; i++) {
		for (int j = 0; j <= L; j++) {
			ans = min(ans, dp[i][j]);
		}
	}
	if (ans > F) {
		return INF;
	}
	return ans;
}

int main() {
	while (true) {
		int H, W;
		cin >> W >> H;
		if (H == 0 && W == 0) {
			break;
		}
		int F, L, O;
		cin >> F >> L >> O;
		vector<vector<int> > C(H, vector<int>(W));
		for (int i = 0; i < H; i++) {
			for (int j = 0; j < W; j++) {
				cin >> C[i][j];
			}
		}
		int ans = solve(H, W, F, L, O, C);
		if (ans != INF) {
			cout << ans << endl;
		}
		else {
			cout << "NA" << endl;
		}
	}
	return 0;
}
accuracy: 1
time_ms: 80
memory_kb: 3456
final_rank: 13

code_snippet: #include <iostream>
#include <tuple>
#include <queue>
#include <vector>
#include <cassert>
#include <algorithm>
#include <functional>
using namespace std;

const int dx[3] = { 0, 0, 1 };
const int dy[3] = { -1, 1, 0 };
int H, W, F, M, O;
int C[119][119];
int Dist[119][119][59];
priority_queue<tuple<int, int, int, int>, vector<tuple<int, int, int, int>>, greater<tuple<int, int, int, int>>> Q;

int main() {
	while (true) {
		// Step 1. Input
		cin >> W >> H; if (W + H == 0) break;
		cin >> F >> M >> O;
		for (int i = 0; i < H; i++) {
			for (int j = 0; j < W; j++) cin >> C[i][j];
		}

		// Step 2. Constraints Check
		assert(3 <= H && H <= 10);
		assert(3 <= W && W <= 10);
		assert(1 <= F && F <= 10000);
		assert(3 <= M && M <= 50);
		assert(0 <= O && O <= M);
		for (int i = 0; i < H; i++) {
			for (int j = 0; j < W; j++) assert(-10000 <= C[i][j] && C[i][j] <= 10000 && C[i][j] != 0);
		}

		// Step 2. Dijkstra Init
		for (int i = 0; i < H * W; i++) {
			for (int j = 0; j < W * W; j++) {
				for (int k = 0; k <= M; k++) Dist[i][j][k] = (1 << 30);
			}
		}
		if (O >= 2) {
			for (int i = 0; i < W; i++) {
				if (C[0][i] >= 1) {
					int oxy = min(M, O - 1 + C[0][i]);
					Dist[i][i * W + i][oxy] = 0;
					Q.push(make_tuple(Dist[i][i * W + i][oxy], i, i * W + i, oxy));
				}
				if (C[0][i] <= -1) {
					Dist[i][i * W + i][O - 1] = -C[0][i];
					Q.push(make_tuple(Dist[i][i * W + i][O - 1], i, i * W + i, O - 1));
				}
			}
		}

		// Step 3. Dijkstra
		while (!Q.empty()) {
			int pos1 = get<1>(Q.top());
			int pos2 = get<2>(Q.top());
			int pos3 = get<3>(Q.top()); Q.pop();
			int sx = pos1 / W;
			int sy = pos1 % W;
			int cl = pos2 / W;
			int cr = pos2 % W;
			if (pos3 == 1) continue;

			for (int i = 0; i < 3; i++) {
				int tx = sx + dx[i];
				int ty = sy + dy[i];
				if (tx < 0 || tx >= H || ty < 0 || ty >= W) continue;
				int dl = cl;
				int dr = cr;
				int rem = pos3 - 1;
				int cost = 0;
				if (i == 2 || ty < dl || dr < ty) {
					if (C[tx][ty] >= 1) rem = min(M, rem + C[tx][ty]);
					if (C[tx][ty] <= -1) cost = -C[tx][ty];
				}
				if (i == 2) { dl = ty; dr = ty; }
				else { dl = min(dl, ty); dr = max(dr, ty); }
				if (Dist[tx * W + ty][dl * W + dr][rem] > Dist[pos1][pos2][pos3] + cost) {
					Dist[tx * W + ty][dl * W + dr][rem] = Dist[pos1][pos2][pos3] + cost;
					Q.push(make_tuple(Dist[tx * W + ty][dl * W + dr][rem], tx * W + ty, dl * W + dr, rem));
				}
			}
		}

		// Step 4. Output
		int Answer = (1 << 30);
		for (int i = 0; i < W; i++) {
			for (int j = 0; j < W * W; j++) {
				for (int k = 1; k <= M; k++) Answer = min(Answer, Dist[(H - 1) * W + i][j][k]);
			}
		}
		if (Answer == (1 << 30)) cout << "NA" << endl;
		else cout << Answer << endl;
	}
	return 0;
}
accuracy: 1
time_ms: 30
memory_kb: 6072
final_rank: 11

code_snippet: #include <iostream>
#include <tuple>
#include <queue>
#include <vector>
#include <algorithm>
#include <functional>
using namespace std;

const int dx[3] = { 0, 0, 1 };
const int dy[3] = { -1, 1, 0 };
int H, W, F, M, O;
int C[119][119];
int Dist[119][119][59];
priority_queue<tuple<int, int, int, int>, vector<tuple<int, int, int, int>>, greater<tuple<int, int, int, int>>> Q;

int main() {
	while (true) {
		// Step 1. Input
		cin >> W >> H; if (W + H == 0) break;
		cin >> F >> M >> O;
		for (int i = 0; i < H; i++) {
			for (int j = 0; j < W; j++) cin >> C[i][j];
		}

		// Step 2. Dijkstra Init
		for (int i = 0; i < H * W; i++) {
			for (int j = 0; j < W * W; j++) {
				for (int k = 0; k <= M; k++) Dist[i][j][k] = (1 << 30);
			}
		}
		if (O >= 2) {
			for (int i = 0; i < W; i++) {
				if (C[0][i] >= 1) {
					int oxy = min(M, O - 1 + C[0][i]);
					Dist[i][i * W + i][oxy] = 0;
					Q.push(make_tuple(Dist[i][i * W + i][oxy], i, i * W + i, oxy));
				}
				if (C[0][i] <= -1) {
					Dist[i][i * W + i][O - 1] = -C[0][i];
					Q.push(make_tuple(Dist[i][i * W + i][O - 1], i, i * W + i, O - 1));
				}
			}
		}

		// Step 3. Dijkstra
		while (!Q.empty()) {
			int pos1 = get<1>(Q.top());
			int pos2 = get<2>(Q.top());
			int pos3 = get<3>(Q.top()); Q.pop();
			int sx = pos1 / W;
			int sy = pos1 % W;
			int cl = pos2 / W;
			int cr = pos2 % W;
			if (pos3 == 1) continue;

			for (int i = 0; i < 3; i++) {
				int tx = sx + dx[i];
				int ty = sy + dy[i];
				if (tx < 0 || tx >= H || ty < 0 || ty >= W) continue;
				int dl = cl;
				int dr = cr;
				int rem = pos3 - 1;
				int cost = 0;
				if (i == 2 || ty < dl || dr < ty) {
					if (C[tx][ty] >= 1) rem = min(M, rem + C[tx][ty]);
					if (C[tx][ty] <= -1) cost = -C[tx][ty];
				}
				if (i == 2) { dl = ty; dr = ty; }
				else { dl = min(dl, ty); dr = max(dr, ty); }
				if (Dist[tx * W + ty][dl * W + dr][rem] > Dist[pos1][pos2][pos3] + cost) {
					Dist[tx * W + ty][dl * W + dr][rem] = Dist[pos1][pos2][pos3] + cost;
					Q.push(make_tuple(Dist[tx * W + ty][dl * W + dr][rem], tx * W + ty, dl * W + dr, rem));
				}
			}
		}

		// Step 4. Output
		int Answer = (1 << 30);
		for (int i = 0; i < W; i++) {
			for (int j = 0; j < W * W; j++) {
				for (int k = 1; k <= M; k++) Answer = min(Answer, Dist[(H - 1) * W + i][j][k]);
			}
		}
		if (Answer == (1 << 30)) cout << "NA" << endl;
		else cout << Answer << endl;
	}
	return 0;
}
accuracy: 1
time_ms: 30
memory_kb: 5988
final_rank: 10

code_snippet: #include <iostream>
#include <tuple>
#include <queue>
#include <vector>
#include <algorithm>
#include <functional>
using namespace std;

const int dx[3] = { 0, 0, 1 };
const int dy[3] = { -1, 1, 0 };
int H, W, F, M, O;
int C[119][119];
int Dist[119][119][59];
priority_queue<tuple<int, int, int, int>, vector<tuple<int, int, int, int>>, greater<tuple<int, int, int, int>>> Q;

int main() {
	while (true) {
		// Step 1. Input
		cin >> W >> H; if (W + H == 0) break;
		cin >> F >> M >> O;
		for (int i = 0; i < H; i++) {
			for (int j = 0; j < W; j++) cin >> C[i][j];
		}

		// Step 2. Dijkstra Init
		for (int i = 0; i < H * W; i++) {
			for (int j = 0; j < W * W; j++) {
				for (int k = 0; k <= M; k++) Dist[i][j][k] = (1 << 30);
			}
		}
		if (O >= 2) {
			for (int i = 0; i < W; i++) {
				if (C[0][i] >= 1) {
					Dist[i][i * W + i][O - 0] = 0;
					Q.push(make_tuple(Dist[i][i * W + i][O - 0], i, i * W + i, O - 0));
				}
				if (C[0][i] <= -1) {
					Dist[i][i * W + i][O - 1] = -C[0][i];
					Q.push(make_tuple(Dist[i][i * W + i][O - 1], i, i * W + i, O - 1));
				}
			}
		}

		// Step 3. Dijkstra
		while (!Q.empty()) {
			int pos1 = get<1>(Q.top());
			int pos2 = get<2>(Q.top());
			int pos3 = get<3>(Q.top()); Q.pop();
			int sx = pos1 / W;
			int sy = pos1 % W;
			int cl = pos2 / W;
			int cr = pos2 % W;
			if (pos3 == 1) continue;

			for (int i = 0; i < 3; i++) {
				int tx = sx + dx[i];
				int ty = sy + dy[i];
				if (tx < 0 || tx >= H || ty < 0 || ty >= W) continue;
				int dl = cl;
				int dr = cr;
				int rem = pos3 - 1;
				int cost = 0;
				if (i == 2 || ty < dl || dr < ty) {
					if (C[tx][ty] >= 1) rem = min(M, rem + C[tx][ty]);
					if (C[tx][ty] <= -1) cost = -C[tx][ty];
				}
				if (i == 2) { dl = ty; dr = ty; }
				else { dl = min(dl, ty); dr = max(dr, ty); }
				if (Dist[tx * W + ty][dl * W + dr][rem] > Dist[pos1][pos2][pos3] + cost) {
					Dist[tx * W + ty][dl * W + dr][rem] = Dist[pos1][pos2][pos3] + cost;
					Q.push(make_tuple(Dist[tx * W + ty][dl * W + dr][rem], tx * W + ty, dl * W + dr, rem));
				}
			}
		}

		// Step 4. Output
		int Answer = (1 << 30);
		for (int i = 0; i < W; i++) {
			for (int j = 0; j < W * W; j++) {
				for (int k = 1; k <= M; k++) Answer = min(Answer, Dist[(H - 1) * W + i][j][k]);
			}
		}
		if (Answer > F) cout << "NA" << endl;
		else cout << Answer << endl;
	}
	return 0;
}
accuracy: 1
time_ms: 30
memory_kb: 6156
final_rank: 12

code_snippet: #include <iostream>
#include <tuple>
#include <queue>
#include <vector>
#include <cassert>
#include <algorithm>
#include <functional>
using namespace std;

const int dx[3] = { 0, 0, 1 };
const int dy[3] = { -1, 1, 0 };
int H, W, F, M, O;
int C[119][119];
int Dist[119][119][59];
priority_queue<tuple<int, int, int, int>, vector<tuple<int, int, int, int>>, greater<tuple<int, int, int, int>>> Q;

int main() {
	while (true) {
		// Step 1. Input
		cin >> W >> H; if (W + H == 0) break;
		cin >> F >> M >> O;
		for (int i = 0; i < H; i++) {
			for (int j = 0; j < W; j++) {
				cin >> C[i][j];
				assert(-10000 <= C[i][j] && C[i][j] <= 10000 && C[i][j] != 0);
			}
		}

		// Step 2. Dijkstra Init
		for (int i = 0; i < H * W; i++) {
			for (int j = 0; j < W * W; j++) {
				for (int k = 0; k <= M; k++) Dist[i][j][k] = (1 << 30);
			}
		}
		if (O >= 2) {
			for (int i = 0; i < W; i++) {
				if (C[0][i] >= 1) {
					Dist[i][i * W + i][O - 0] = 0;
					Q.push(make_tuple(Dist[i][i * W + i][O - 0], i, i * W + i, O - 0));
				}
				if (C[0][i] <= -1) {
					Dist[i][i * W + i][O - 1] = -C[0][i];
					Q.push(make_tuple(Dist[i][i * W + i][O - 1], i, i * W + i, O - 1));
				}
			}
		}

		// Step 3. Dijkstra
		while (!Q.empty()) {
			int pos1 = get<1>(Q.top());
			int pos2 = get<2>(Q.top());
			int pos3 = get<3>(Q.top()); Q.pop();
			int sx = pos1 / W;
			int sy = pos1 % W;
			int cl = pos2 / W;
			int cr = pos2 % W;
			if (pos3 == 1) continue;

			for (int i = 0; i < 3; i++) {
				int tx = sx + dx[i];
				int ty = sy + dy[i];
				if (tx < 0 || tx >= H || ty < 0 || ty >= W) continue;
				int dl = cl;
				int dr = cr;
				int rem = pos3 - 1;
				int cost = 0;
				if (i == 2 || ty < dl || dr < ty) {
					if (C[tx][ty] >= 1) rem = min(M, rem + C[tx][ty]);
					if (C[tx][ty] <= -1) cost = -C[tx][ty];
				}
				if (i == 2) { dl = ty; dr = ty; }
				else { dl = min(dl, ty); dr = max(dr, ty); }
				if (Dist[tx * W + ty][dl * W + dr][rem] > Dist[pos1][pos2][pos3] + cost) {
					Dist[tx * W + ty][dl * W + dr][rem] = Dist[pos1][pos2][pos3] + cost;
					Q.push(make_tuple(Dist[tx * W + ty][dl * W + dr][rem], tx * W + ty, dl * W + dr, rem));
				}
			}
		}

		// Step 4. Output
		int Answer = (1 << 30);
		for (int i = 0; i < W; i++) {
			for (int j = 0; j < W * W; j++) {
				for (int k = 1; k <= M; k++) Answer = min(Answer, Dist[(H - 1) * W + i][j][k]);
			}
		}
		if (Answer == (1 << 30)) cout << "NA" << endl;
		else cout << Answer << endl;
	}
	return 0;
}
accuracy: 1
time_ms: 20
memory_kb: 5988
final_rank: 7

code_snippet: #include <iostream>
#include <tuple>
#include <queue>
#include <vector>
#include <algorithm>
#include <functional>
using namespace std;

const int dx[3] = { 0, 0, 1 };
const int dy[3] = { -1, 1, 0 };
int H, W, F, M, O;
int C[119][119];
int Dist[119][119][59];
priority_queue<tuple<int, int, int, int>, vector<tuple<int, int, int, int>>, greater<tuple<int, int, int, int>>> Q;

int main() {
	while (true) {
		// Step 1. Input
		cin >> W >> H; if (W + H == 0) break;
		cin >> F >> M >> O;
		for (int i = 0; i < H; i++) {
			for (int j = 0; j < W; j++) cin >> C[i][j];
		}

		// Step 2. Dijkstra Init
		for (int i = 0; i < H * W; i++) {
			for (int j = 0; j < W * W; j++) {
				for (int k = 0; k <= M; k++) Dist[i][j][k] = (1 << 30);
			}
		}
		if (O >= 2) {
			for (int i = 0; i < W; i++) {
				if (C[0][i] >= 1) {
					Dist[i][i * W + i][O - 0] = 0;
					Q.push(make_tuple(Dist[i][i * W + i][O - 0], i, i * W + i, O - 0));
				}
				if (C[0][i] <= -1) {
					Dist[i][i * W + i][O - 1] = -C[0][i];
					Q.push(make_tuple(Dist[i][i * W + i][O - 1], i, i * W + i, O - 1));
				}
			}
		}

		// Step 3. Dijkstra
		while (!Q.empty()) {
			int pos1 = get<1>(Q.top());
			int pos2 = get<2>(Q.top());
			int pos3 = get<3>(Q.top()); Q.pop();
			int sx = pos1 / W;
			int sy = pos1 % W;
			int cl = pos2 / W;
			int cr = pos2 % W;
			if (pos3 == 1) continue;

			for (int i = 0; i < 3; i++) {
				int tx = sx + dx[i];
				int ty = sy + dy[i];
				if (tx < 0 || tx >= H || ty < 0 || ty >= W) continue;
				int dl = cl;
				int dr = cr;
				int rem = pos3 - 1;
				int cost = 0;
				if (i == 2 || ty < dl || dr < ty) {
					if (C[tx][ty] >= 1) rem = min(M, rem + C[tx][ty]);
					if (C[tx][ty] <= -1) cost = -C[tx][ty];
				}
				if (i == 2) { dl = ty; dr = ty; }
				else { dl = min(dl, ty); dr = max(dr, ty); }
				if (Dist[tx * W + ty][dl * W + dr][rem] > Dist[pos1][pos2][pos3] + cost) {
					Dist[tx * W + ty][dl * W + dr][rem] = Dist[pos1][pos2][pos3] + cost;
					Q.push(make_tuple(Dist[tx * W + ty][dl * W + dr][rem], tx * W + ty, dl * W + dr, rem));
				}
			}
		}

		// Step 4. Output
		int Answer = (1 << 30);
		for (int i = 0; i < W; i++) {
			for (int j = 0; j < W * W; j++) {
				for (int k = 1; k <= M; k++) Answer = min(Answer, Dist[(H - 1) * W + i][j][k]);
			}
		}
		if (Answer == (1 << 30)) cout << "NA" << endl;
		else cout << Answer << endl;
	}
	return 0;
}
accuracy: 1
time_ms: 20
memory_kb: 6144
final_rank: 8

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll = long long;

int main(){
    ios::sync_with_stdio(false);
    cin.tie(0);
    int w, h;
    while(cin >> w >> h, h){
        int f, m, o;
        cin >> f >> m >> o;
        vector<vector<int>> C(h + 1, vector<int>(w));
        for(int y = 0; y < h; y++){
            for(int x = 0; x < w; x++){
                cin >> C[y][x];
            }
        }
        //空けた場所,現在の位置,現在の酸素
        vector<vector<vector<int>>> dp(1 << w, vector<vector<int>>(w, vector<int>(m + 1, 1 << 30)));
        for(int i = 0; i < (1 << w); i++){
            for(int j = 0; j < w; j++){
                dp[i][j][o] = 0;
            }
        }
        for(int i = 0; i < h; i++){
            vector<vector<vector<int>>> ndp(1 << w, vector<vector<int>>(w, vector<int>(m + 1, 1 << 30)));
            for(int j = 0; j < (1 << w); j++){
                for(int k = 0; k < w; k++){
                    for(int l = 2; l <= m; l++){
                        if(dp[j][k][l] >> 30 & 1)continue;
                        if(C[i][k] >= 0){
                            ndp[1 << k][k][min(m, l - 1 + C[i][k])] 
                                = min(ndp[1 << k][k][min(m, l - 1 + C[i][k])], dp[j][k][l]);
                        }else{
                            ndp[1 << k][k][l - 1] 
                                = min(ndp[1 << k][k][l - 1], dp[j][k][l] - C[i][k]);
                        }
                    }
                }
            }
            swap(dp, ndp);
            for(int t = 0; t < 20; t++){
                for(int j = 0; j < (1 << w); j++){
                    for(int k = 0; k < w; k++){
                        for(int l = 2; l <= m; l++){
                            if(dp[j][k][l] >> 30 & 1)continue;
                            if(k >= 1){
                                if(j >> (k - 1) & 1){
                                    dp[j][k - 1][l - 1] = min(dp[j][k - 1][l - 1], dp[j][k][l]);
                                }else if(C[i][k - 1] >= 0){
                                    dp[j | (1 << (k - 1))][k - 1][min(m, l - 1 + C[i][k - 1])] 
                                        = min(dp[j | (1 << (k - 1))][k - 1][min(m, l - 1 + C[i][k - 1])], 
                                            dp[j][k][l]);
                                }else{
                                    dp[j | (1 << (k - 1))][k - 1][l - 1] 
                                        = min(dp[j | (1 << (k - 1))][k - 1][l - 1], 
                                            dp[j][k][l] - C[i][k - 1]);
                                }
                            }
                            if(k + 1 < w){
                                if(j >> (k + 1) & 1){
                                    dp[j][k + 1][l - 1] = min(dp[j][k + 1][l - 1], dp[j][k][l]);
                                }else if(C[i][k + 1] >= 0){
                                    dp[j | (1 << (k + 1))][k + 1][min(m, l - 1 + C[i][k + 1])] 
                                        = min(dp[j | (1 << (k + 1))][k + 1][min(m, l - 1 + C[i][k + 1])], 
                                            dp[j][k][l]);
                                }else{
                                    dp[j | (1 << (k + 1))][k + 1][l - 1] 
                                        = min(dp[j | (1 << (k + 1))][k + 1][l - 1], 
                                            dp[j][k][l] - C[i][k + 1]);
                                }
                            }
                        }
                    }
                }
            }
        }
        int ans = 1 << 30;
        for(int i = 0; i < (1 << w); i++){
            for(int j = 0; j < w; j++){
                for(int k = 1; k <= m; k++){
                    ans = min(ans, dp[i][j][k]);
                }
            }
        }
        if(ans > f)cout << "NA" << '\n';
        else cout << ans << '\n';
    }
}
accuracy: 1
time_ms: 100
memory_kb: 6884
final_rank: 14

code_snippet: #include<iostream>
#include<queue>
#include<algorithm>
using namespace std;
int H,W,F,M,o;
int c[10][10];
int dist[10][10][1<<10][51];
main()
{
	while(cin>>W>>H,H)
	{
		cin>>F>>M>>o;
		for(int i=0;i<H;i++)for(int j=0;j<W;j++)cin>>c[i][j];
		for(int i=0;i<H;i++)for(int j=0;j<W;j++)
			for(int k=0;k<1<<W;k++)for(int l=0;l<=M;l++)dist[i][j][k][l]=F+1;
		priority_queue<pair<int,pair<pair<int,int>,pair<int,int> > > >P;
		for(int j=0;j<W;j++)
		{
			if(c[0][j]<0&&o>0)
			{
				dist[0][j][1<<j][o-1]=-c[0][j];
				P.push(make_pair(c[0][j],make_pair(make_pair(0,j),make_pair(1<<j,o-1))));
			}
			else if(o>1)
			{
				dist[0][j][1<<j][min(M,o-1+c[0][j])]=0;
				P.push(make_pair(0,make_pair(make_pair(0,j),make_pair(1<<j,min(M,o-1+c[0][j])))));
			}
		}
		int ans=F+1;
		while(!P.empty())
		{
			int i=P.top().second.first.first;
			int j=P.top().second.first.second;
			int J=P.top().second.second.first;
			int o=P.top().second.second.second;
			int cost=-P.top().first;
			P.pop();
			if(o==0||dist[i][j][J][o]<cost)continue;
			if(i==H-1)
			{
				ans=min(ans,cost);
				continue;
			}
			else
			{
				int nxt=cost;
				int no=o-1;
				if(c[i+1][j]<0)
				{
					nxt+=-c[i+1][j];
				}
				else if(no>0)
				{
					no+=c[i+1][j];
					if(no>M)no=M;
				}
				int nj=1<<j;
				if(dist[i+1][j][nj][no]>nxt)
				{
					dist[i+1][j][nj][no]=nxt;
					P.push(make_pair(-nxt,make_pair(make_pair(i+1,j),make_pair(nj,no))));
				}
			}
			if(j>0)
			{
				int nxt=cost;
				int no=o-1;
				if(J>>j-1&1)
				{
				}
				else if(c[i][j-1]<0)
				{
					nxt+=-c[i][j-1];
				}
				else if(no>0)
				{
					no+=c[i][j-1];
					if(no>M)no=M;
				}
				int nj=J|1<<j-1;
				if(dist[i][j-1][nj][no]>nxt)
				{
					dist[i][j-1][nj][no]=nxt;
					P.push(make_pair(-nxt,make_pair(make_pair(i,j-1),make_pair(nj,no))));
				}
			}
			if(j<W-1)
			{
				int nxt=cost;
				int no=o-1;
				if(J>>j+1&1)
				{
				}
				else if(c[i][j+1]<0)
				{
					nxt+=-c[i][j+1];
				}
				else if(no>0)
				{
					no+=c[i][j+1];
					if(no>M)no=M;
				}
				int nj=J|1<<j+1;
				if(dist[i][j+1][nj][no]>nxt)
				{
					dist[i][j+1][nj][no]=nxt;
					P.push(make_pair(-nxt,make_pair(make_pair(i,j+1),make_pair(nj,no))));
				}
			}
		}
		if(ans>F)cout<<"NA"<<endl;
		else cout<<ans<<endl;
	}
}
accuracy: 1
time_ms: 30
memory_kb: 23584
final_rank: 15

code_snippet: #include <iostream>
#include <algorithm>
#include <map>
#include <set>
#include <queue>
#include <stack>
#include <numeric>
#include <bitset>
#include <cmath>

static const int MOD = 1000000007;
using ll = long long;
using u32 = unsigned;
using u64 = unsigned long long;
using namespace std;

template<class T> constexpr T INF = ::numeric_limits<T>::max()/32*15+208;

template <class T, class U>
vector<T> make_v(U size, const T& init){ return vector<T>(static_cast<size_t>(size), init); }

template<class... Ts, class U>
auto make_v(U size, Ts... rest) { return vector<decltype(make_v(rest...))>(static_cast<size_t>(size), make_v(rest...)); }

template<class T> inline bool chmin(T &a, const T &b){ return a > b && (a = b, true); }
template<class T> inline bool chmax(T &a, const T &b){ return a < b && (a = b, true); }

template <class K, class V>
class RadixHeap {
    static constexpr int bit_length = sizeof(K)*8;
    K last;
    size_t sz, cnt;
    array<vector<pair<K, V>>, bit_length> v;
    static inline int bsr(int x){
        return x ? bit_length-__builtin_clz(x) : 0;
    }
    static inline int bsr(ll x){
        return x ? bit_length-__builtin_clzll(x) : 0;
    }

    void pull() {
        if(cnt < v[0].size()) return;;
        int i = 1;
        while(v[i].empty()) i++;
        last = min_element(v[i].begin(),v[i].end())->first;
        for (auto &&x : v[i]) v[bsr(x.first ^ last)].push_back(x);
        v[i].clear();
    }
public:
    RadixHeap() : last(0), sz(0), cnt(0) {}
    void emplace(K x, V val){
        sz++;
        v[bsr(x^last)].emplace_back(x, val);
    }

    pair<K, V> top() {
        pull();
        return v[0][cnt];
    }

    void pop() {
        pull();
        sz--;
        cnt++;
    }

    size_t size() const { return sz; }
    bool empty() const { return !sz; }
};

void solve(int w, int h){
    int f, m, o;
    cin >> f >> m >> o;
    auto dp = make_v(h, w, w, w, m+1, INF<int>); // i, j, l, r, O;
    auto v = make_v(h, w, 0);
    for (int i = 0; i < h; ++i) {
        for (int j = 0; j < w; ++j) {
            cin >> v[i][j];
        }
    }
    if(o <= 1) {
        puts("NA");
        return;
    }
    using P = tuple<int, int, int, int, int>;
    RadixHeap<int, P> Q;
    for (int i = 0; i < w; ++i) {
        dp[0][i][i][i][min(m, o+max(0, v[0][i])-1)] = max(0, -v[0][i]);
        Q.emplace(max(0, -v[0][i]), P{0, i, i, i, min(m, o+max(0, v[0][i])-1)});
    }
    while(!Q.empty()){
        int a, b, c, d, e; int cost;  tuple<int, int, int, int, int> A;
        tie(cost, A) = Q.top(); Q.pop();
        tie(a, b, c, d, e) = A;
        if(dp[a][b][c][d][e] < cost) continue;
        if(e <= 1) continue;
        if(a+1 < h){
            int ccost = cost + max(0, -v[a+1][b]);
            int ee = min(m, e-1+max(0, v[a+1][b]));
            if(chmin(dp[a+1][b][b][b][ee], ccost)){
                Q.emplace(ccost, P{a+1, b, b, b, ee});
            }
        }
        if(b){
            int ccost = cost + (b == c ? max(0, -v[a][b-1]) : 0);
            int ee = min(m, e-1+(b == c ? max(0, v[a][b-1]) : 0));
            if(chmin(dp[a][b-1][min(c, b-1)][d][ee], ccost)){
                Q.emplace(ccost, P{a, b-1, min(c, b-1), d, ee});
            }
        }
        if(b != w-1){
            int ccost = cost + (b == d ? max(0, -v[a][b+1]) : 0);
            int ee = min(m, e-1+(b == d ? max(0, v[a][b+1]) : 0));
            if(chmin(dp[a][b+1][c][max(d, b+1)][ee], ccost)){
                Q.emplace(ccost, P{a, b+1, c, max(d, b+1), ee});
            }
        }
    }
    int ans = INF<int>;
    for (int i = 0; i < w; ++i) {
        for (int j = 0; j < w; ++j) {
            for (int k = 0; k < w; ++k) {
                for (int l = 1; l <= m; ++l) {
                    chmin(ans, dp.back()[i][j][k][l]);
                }
            }
        }
    }
    if(ans >= f) puts("NA");
    else cout << ans << "\n";
}

int main() {
    int w, h;
    while(cin >> w >> h, w){
        solve(w, h);
    }
    return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 7000
final_rank: 6

code_snippet: #include <stdio.h>
#include <cmath>
#include <algorithm>
#include <cfloat>
#include <stack>
#include <queue>
#include <vector>
#include <string>
#include <iostream>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;

struct Info{
	Info(){
		row = col = oxyzen = cost = 0;
	}

	Info(int arg_row,int arg_col,int arg_oxyzen,int arg_cost){
		row = arg_row;
		col = arg_col;
		oxyzen = arg_oxyzen;
		cost = arg_cost;
	}

	int row,col,oxyzen,cost;
	bool visited[10][10];
};

int H,W,diff_row[3] = {0,0,1},diff_col[3] = {-1,1,0};
int min_cost[10][10][51];
int map[10][10];

bool rangeCheck(int row,int col){
	if(row >= 0 && row <= H-1 && col >= 0 && col <= W-1)return true;
	else{
		return false;
	}
}

void func(){

	int budget,Limit,first_oxyzen;

	scanf("%d %d %d",&budget,&Limit,&first_oxyzen);

	for(int i = 0; i < H; i++){
		for(int k = 0; k < W; k++){
			scanf("%d",&map[i][k]);
		}
	}

	if(first_oxyzen == 1){
		printf("NA\n");
		return;
	}

	queue<Info> Q;

	int minimum = BIG_NUM;
	int next_row,next_col;


	for(int start_col = 0; start_col < W; start_col++){

		for(int row = 0; row <= H-1; row++){
			for(int col = 0; col <= W-1; col++){
				for(int oxy = 0; oxy <= Limit; oxy++){
					min_cost[row][col][oxy] = BIG_NUM;
				}
			}
		}

		Info first;
		for(int row = 0; row < H; row++){
			for(int col = 0; col < W; col++){
				first.visited[row][col] = false;
			}
		}

		first.oxyzen = first_oxyzen-1;
		first.cost = 0;
		first.row = 0;
		first.col = start_col;
		first.visited[0][start_col] = true;

		if(map[0][start_col] > 0){
			first.oxyzen = min(first.oxyzen+map[0][start_col],Limit);

		}else{
			first.cost += abs(map[0][start_col]);
			if(first.cost > budget){
				continue;
			}
		}

		min_cost[0][start_col][first.oxyzen] = first.cost;

		Q.push(first);

		while(!Q.empty()){

			if(Q.front().row == H-1){
				Q.pop();
			}else if(Q.front().cost > min_cost[Q.front().row][Q.front().col][Q.front().oxyzen] || Q.front().oxyzen == 1){
				Q.pop();
			}else{

				for(int i = 0; i < 3; i++){
					next_row = Q.front().row + diff_row[i];
					next_col = Q.front().col + diff_col[i];

					if(!rangeCheck(next_row,next_col))continue;

					Info next_info;
					next_info.row = next_row;
					next_info.col = next_col;
					next_info.oxyzen = Q.front().oxyzen-1;
					next_info.cost = Q.front().cost;

					for(int row = 0; row < H; row++){
						for(int col = 0; col < W; col++){
							next_info.visited[row][col] = Q.front().visited[row][col];
						}
					}

					if(map[next_row][next_col] > 0 && next_info.visited[next_row][next_col] == false){
						next_info.oxyzen = min(next_info.oxyzen+map[next_row][next_col],Limit);
					}else{
						if(next_info.visited[next_row][next_col] == false){
							next_info.cost += abs(map[next_row][next_col]);
							if(next_info.cost > budget){
								continue;
							}
						}
					}

					next_info.visited[next_row][next_col] = true;

					if(min_cost[next_row][next_col][next_info.oxyzen] > next_info.cost){
						min_cost[next_row][next_col][next_info.oxyzen] = next_info.cost;
						Q.push(next_info);
					}
				}
				Q.pop();
			}
		}

		for(int col = 0; col < W; col++){
			for(int oxy = 0; oxy <= Limit; oxy++){
				minimum = min(minimum,min_cost[H-1][col][oxy]);
			}
		}
	}

	if(minimum == BIG_NUM){
		printf("NA\n");
	}else{
		printf("%d\n",minimum);
	}

}

int main(){

	while(true){
		scanf("%d %d",&W,&H);
		if(W == 0 && H == 0)break;

		func();
	}
	return 0;
}
accuracy: 1
time_ms: 30
memory_kb: 3140
final_rank: 4

code_snippet: #include<bits/stdc++.h>
using namespace std;
#define rep(i, n) for ( int i = 0; i < n ;i++ )
#define MAX 100
int H, W;
int dy[3] = { 0, 0, 1 }; int dx[3] = { 1, -1, 0 };
class State {public:	int l, r, y, x, o;
	State(int y = 0, int x = 0, int o = 0) :y(y), x(x), o(o) {reset();}
	void reset() {l = W;r = -1;}
	void visit(int j) {l = min(l, j);r = max(r, j);}
	bool visited(int j) {return l <= j && j <= r;}
	bool operator <(const State &s) const {
		if (o != s.o)return o < s.o;
		if (l != s.l)	return l < s.l;
		if (r != s.r)return r < s.r;
		if (y != s.y)return y < s.y;
		if (x != s.x)return x < s.x;
		return false;
	}
};
class QState {public:	State state;int cost;  QState() {}
	QState(State state, int cost) :state(state), cost(cost) {}
	bool operator <(const QState &s) const {return cost > s.cost;	}
};
int F, M, O, C[MAX][MAX];
int dijkstra() {
	if (O == 0)return -1;
	int ncost;	priority_queue<QState> PQ;	set<State> visited;
	rep(j, W){
		State source = State(0, j, O);
		source.visit(j);
		source.o--;
		if (source.o == 0)continue;
		if (C[0][j] >= 0) {
			source.o = min(M, source.o + C[0][j]);
			ncost = 0;
		} else {	ncost = C[0][j] * (-1);
		}
		visited.insert(source);
		PQ.push(QState(source, ncost));
	}
	QState u, v;int nx, ny;
	while (!PQ.empty()) {
		u = PQ.top();PQ.pop();
		if (u.cost > F)continue;
		if (u.state.y == H - 1)return u.cost;
		rep(r, 3){
			nx = u.state.x + dx[r]; ny = u.state.y + dy[r];
			if (nx < 0 || ny < 0 || nx >= W || ny >= H)continue;
			v = u;
			v.state.o--;
			if (v.state.o == 0)	continue;
			v.state.x = nx;v.state.y = ny;
			if (r == 2)	v.state.reset();
			if (!v.state.visited(nx)) {
				if (C[ny][nx] >= 0) {
					v.state.o = min(M, v.state.o + C[ny][nx]);
					v.state.visit(nx);
				} else if (C[ny][nx] < 0) {
					v.cost = u.cost + (C[ny][nx] * (-1));
					v.state.visit(nx);
				}
			}
			if (visited.find(v.state) == visited.end()) {
				visited.insert(v.state);
				PQ.push(v);
			}
		}
	}
	return -1;
}
int main() {	while( cin >> W >> H && W && H ) {
		cin >> F >> M >> O;
		rep(i, H) rep(j, W) cin >> C[i][j];
		int cost = dijkstra();
		if ( cost < 0 || F < cost) cout << "NA" << endl;
		else cout << cost << endl;}return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 3284
final_rank: 2

code_snippet: #include<bits/stdc++.h>
#define INF 0x3f3f3f3f
#define rep(i,n)for(int i=0;i<(n);i++)
using namespace std;

int c[11][10], d[11][10][55][1 << 10];
int dx[]{ 1,0,0 }, dy[]{ 0,1,-1 };
struct st { int x, y, p, v, c; };
bool operator<(st a, st b) { return a.c > b.c; }
int main() {
	int w, h;
	while (scanf("%d%d", &w, &h), w) {
		int f, m, o; scanf("%d%d%d", &f, &m, &o);
		rep(i, h)rep(j, w)scanf("%d", &c[i + 1][j]);
		priority_queue<st>que;
		memset(d, 0x3f, sizeof(d));
		rep(i, w) {
			d[0][i][o][0] = 0; que.push({ 0,i,o,0,0 });
		}
		while (!que.empty()) {
			st p = que.top(); que.pop();
			if (d[p.x][p.y][p.p][p.v] != p.c)continue;
			if (p.p == 1)continue;
			rep(i, 3) {
				int nx = p.x + dx[i], ny = p.y + dy[i];
				if (!(nx <= h && 0 <= ny&&ny < w))continue;
				int a = min(m, ((c[nx][ny] > 0 && (!i || !(p.v >> ny & 1))) ? p.p - 1 + c[nx][ny] : p.p - 1));
				if (a <= 0)continue;
				int b = ((c[nx][ny] < 0 && (!i || !(p.v >> ny & 1))) ? p.c - c[nx][ny] : p.c);
				int e = ((i ? p.v : 0) | 1 << ny);
				if (d[nx][ny][a][e] > b) {
					d[nx][ny][a][e] = b; que.push({ nx,ny,a,e,b });
				}
			}
		}
		int Min = INF;
		rep(i, w)rep(j, m + 1)rep(k, 1 << w)Min = min(Min, d[h][i][j][k]);
		if (Min > f)puts("NA");
		else printf("%d\n", Min);
	}
}
accuracy: 1
time_ms: 90
memory_kb: 27576
final_rank: 17

code_snippet: #include<bits/stdc++.h>
using namespace std;

const int INF = 1001001001;

int W, H, F, M, O;
int fld[15][15];

struct data {
	int y, x, s, o, f;
	data(int y, int x, int s, int o, int f)
		:y(y), x(x), s(s), o(o), f(f) {}

	bool operator<(const data &d)const {
		return f>d.f;
	}
};

int dist[15][15][1 << 10][50];

void solve() {
	fill_n(***dist, 15 * 15 * (1 << 10) * 50, INF);
	priority_queue<data>que;
	for (int i = 0; i<W; i++) {
		dist[0][i][1 << i][O] = 0;
		que.push(data(0, i, 1 << i, O, 0));
	}

	while (que.size()) {
		data d = que.top(); que.pop();
		if (dist[d.y][d.x][d.s][d.o]<d.f)continue;
		if (d.o == 0)continue;
		for (int i = -1; i <= 1; i += 2) {
			int ny = d.y, nx = d.x + i;
			if (nx<0 || nx >= W)continue;
			int ns, no, nf;
			if (d.s >> nx & 1) {
				ns = d.s; no = d.o - 1; nf = d.f;
			}
			else {
				ns = d.s | (1 << nx);
				no = min(M, d.o - 1 + (fld[ny][nx] >= 0 ? fld[ny][nx] : 0));
				nf = d.f + (fld[ny][nx] >= 0 ? 0 : -fld[ny][nx]);
			}
			if (no<0)continue;
			if (dist[ny][nx][ns][no] <= nf)continue;
			dist[ny][nx][ns][no] = nf;
			que.push(data(ny, nx, ns, no, nf));
		}

		int ny = d.y + 1, nx = d.x;
		if (ny>H)continue;
		int ns, no, nf;
		ns = 1 << nx;
		no = min(M, d.o - 1 + (fld[ny][nx] >= 0 ? fld[ny][nx] : 0));
		nf = d.f + (fld[ny][nx] >= 0 ? 0 : -fld[ny][nx]);
		if (no<0)continue;
		if (dist[ny][nx][ns][no] <= nf)continue;
		dist[ny][nx][ns][no] = nf;
		que.push(data(ny, nx, ns, no, nf));
	}

	int mi = INF;
	for (int j = 0; j<W; j++) {
		for (int o = 0; o <= M; o++) {
			mi = min(mi, dist[H][j][1 << j][o]);
		}
	}

	if (mi>F)cout << "NA" << endl;
	else cout << mi << endl;
}

int main() {
	while (cin >> W >> H, W || H) {
		cin >> F >> M >> O; M--; O--;
		for (int i = 1; i <= H; i++) {
			for (int j = 0; j<W; j++) {
				cin >> fld[i][j];
			}
		}
		solve();
	}
	return 0;
}
accuracy: 1
time_ms: 290
memory_kb: 48228
final_rank: 20

code_snippet: #include <iostream>
#include <string.h>
#include <algorithm>

using namespace std;
static const int INF = 1e9;
int memo[10][10][10][10][50];
int W, H;
int field[10][10];
int f, o, olimit;


int rec(int y, int x, int l, int r, int oxy)
{
	if (oxy <= 0)
	{
		return(INF);
	}
	if (y == H - 1)
	{
		return(0);
	}
	if (memo[y][x][l][r][oxy] >= 0)
	{
		return(memo[y][x][l][r][oxy]);
	}

	if (oxy == 1) return (INF);

	int cost = 0;
	int oxygen = 0;
	int res = INF;
	if (x > 0)
	{
		if (l > x - 1)
		{
			if (field[y][x - 1] < 0)
			{
				cost = -field[y][x - 1];
			}
			else
			{
				oxygen = field[y][x - 1];
			}
		}
		res = min(res, rec(y, x - 1, min(l, x - 1), r, min(olimit, oxy + oxygen - 1)) + cost);
	}
	if (x < W - 1)
	{
		cost = 0;
		oxygen = 0;
		if (x + 1 > r)
		{
			if (field[y][x + 1] < 0)
			{
				cost = -field[y][x + 1];
			}
			else
			{
				oxygen = field[y][x + 1];
			}
		}
		res = min(res, rec(y, x + 1, l, max(r, x + 1), min(olimit, oxy + oxygen - 1)) + cost);
	}

	cost = 0;
	oxygen = 0;
	if (field[y + 1][x] < 0)
	{
		cost = -field[y + 1][x];
	}
	else
	{
		oxygen = field[y + 1][x];
	}
	res = min(res, rec(y + 1, x, x, x, min(olimit, oxy + oxygen - 1)) + cost);
	return(memo[y][x][l][r][oxy] = res);
}

void solve()
{
	while (cin >> W >> H, W || H)
	{
		cin >> f >> olimit >> o;
		for (int i = 0; i < H; ++i)
		{
			for (int j = 0; j < W; ++j)
			{
				cin >> field[i][j];
			}
		}
		if (o <= 1)
		{
			cout << "NA" << endl;
			continue;
		}
		memset(memo, -1, sizeof(memo));
		int ans = INF;
		for (int i = 0; i < W; ++i)
		{
			int cost = 0;
			int oxy = 0;
			if (field[0][i] < 0)
			{
				cost = -field[0][i];
			}
			else
			{
				oxy = field[0][i];
			}
			ans = min(ans, rec(0, i, i, i, min(olimit, o + oxy - 1)) + cost);
		}
		if (ans == INF || ans > f)
		{
			cout << "NA" << endl;
		}
		else
		{
			cout << ans << endl;
		}
	}
}

int main()
{
	solve();
	return(0);
}
accuracy: 1
time_ms: 10
memory_kb: 3172
final_rank: 1

code_snippet: #include<bits/stdc++.h>
using namespace std;
int g[12][12][60][12][12];//y, x, air, l, r
int event[12][12];
int w, h, f, m, o;
int dx[] = {1, 0, -1}, dy[] = {0, 1, 0};

typedef struct state{
  int cost, air, x, y, l, r;
  bool operator<(const state &a)const{
    return cost < a.cost;
  }
  bool operator>(const state &a)const{
    return cost > a.cost;
  }
}state;

bool range(int y, int x){
  return (0 <= x and x < w and
          0 <= y and y < h);
}

void solve(){
  priority_queue<state, vector<state>, greater<state> > que;
  for (int i = 0; i < w; i++) {
    if(m <= 1)continue;
    if(event[0][i] < 0){
      g[0][i][m - 1][i][i] = -event[0][i];
      state tmp = (state){-event[0][i], m - 1, i, 0, i, i};
      que.push(tmp);
    }else{
      int air = min(o, m + event[0][i] - 1);
      g[0][i][air][i][i] = 0;
      state tmp = (state){0, air, i, 0, i, i};
      que.push(tmp);
    } 
  }
  while(not que.empty()){
    state tmp = que.top();
    que.pop();
    int l = tmp.l, r = tmp.r;
    int cost = tmp.cost;
    int air = tmp.air;
    int x = tmp.x, y = tmp.y;
    if(air <= 1)continue;
    for (int i = 0; i < 3; i++) {
      int nx = x + dx[i], ny = y + dy[i];
      if(not range(ny, nx))continue;
      int nl = min(l, nx), nr = max(r, nx);
      if(y != ny){
        nl = nx;
        nr = nx;
      }
      if(event[ny][nx] < 0){
        int add = -event[ny][nx];
        if(l <= nx and nx <= r and y == ny)add = 0;
        if(g[ny][nx][air - 1][nl][nr] > cost + add){
          g[ny][nx][air - 1][nl][nr] = cost + add;
          int c = cost + add;
          tmp = (state){c, air - 1, nx, ny, nl, nr};
          que.push(tmp);
        }
      }else{
        int nair = min(air - 1 + event[ny][nx], o);
        if(l <= nx and nx <= r and y == ny)
          nair = air - 1;
        if(g[ny][nx][nair][nl][nr] > cost){
          g[ny][nx][nair][nl][nr] = cost;
          tmp = (state){cost, nair, nx, ny, nl, nr};
          que.push(tmp);
        }
      }
    }
  }
}

void init(){
  for (int i = 0; i < h; i++) 
    for (int j = 0; j < w; j++) 
      for (int k = 0; k <= o; k++) 
        for (int l = 0; l < w; l++) 
          for (int m = 0; m < w; m++) 
            g[i][j][k][l][m] = 1e9;
}


int main(){
  while(std::cin >> w >> h, w){
    std::cin >> f >> o >> m;
    for (int i = 0; i < h; i++) {
      for (int j = 0; j < w; j++) {
        std::cin >> event[i][j];
      }
    }
    init();
    solve();
    int ans = 1e9;
    for (int i = 0; i < w; i++) {
      for (int j = 1; j <= o; j++) {
        for (int k = 0; k < w; k++) {
          for (int l = 0; l < w; l++) {
            ans = min(ans, g[h - 1][i][j][k][l]);
          }
        }
      }
    }
    if(ans > f)std::cout << "NA" << std::endl;
    else std::cout << ans << std::endl;
  }
  return 0;
}
accuracy: 1
time_ms: 30
memory_kb: 4924
final_rank: 9

code_snippet: #include<bits/stdc++.h>
#define rep(i,n) for(int i=0;i<(int)(n);i++)
using namespace std;
typedef vector<int> vi;
typedef long double D;

int d[12][11][11][11][55]; //d[curh][curw][l][r][oxy]

int main(){
  int w,h;
  while(cin >> w >> h, w){
    int f, m, o;
    cin >> f >> m >> o;

    vector<vi> c(h, vi(w,0));
    rep(i,h)rep(j,w)cin >> c[i][j];

    if(o<=1){
      cout << "NA" << endl;
      continue;
    }

    memset(d,-1,sizeof(d));
    priority_queue< vi, vector<vi>, greater<vi> > q;

    rep(i,w){
      int no = o-1, nv = 0;
      if(c[0][i] > 0){
	no = min(m, no+c[0][i]);
      }else{
	nv = -c[0][i];
      }
      d[0][i][i][i][no] = nv;
      q.push( {nv,0,i,i,i,no} );
    }

    int ans = 1e9;
    while(q.size()){
      vi s = q.top(); q.pop();
      int v = s[0], y = s[1], x = s[2], l = s[3], r = s[4], o = s[5];
      if(y==h-1){
	ans = v;
	break;
      }
      if(o<=1)continue;

      if(x-1>=0){
	int nx = x-1, ny = y, nl = l, nr = r, no = o-1, nv = v;
	if(nx < nl){
	  nl--;
	  if(c[ny][nx] > 0){
	    no = min(m, no+c[ny][nx]);
	  }else{
	    nv -= c[ny][nx];
	  }
	}
	if(d[ny][nx][nl][nr][no] < 0 || d[ny][nx][nl][nr][no] > nv){
	  d[ny][nx][nl][nr][no] = nv;
	  q.push( {nv,ny,nx,nl,nr,no} );
	}
      }

      if(x+1<w){
	int nx = x+1, ny = y, nl = l, nr = r, no = o-1, nv = v;
	if(nx > nr){
	  nr++;
	  if(c[ny][nx] > 0){
	    no = min(m, no+c[ny][nx]);
	  }else{
	    nv -= c[ny][nx];
	  }
	}
	if(d[ny][nx][nl][nr][no] < 0 || d[ny][nx][nl][nr][no] > nv){
	  d[ny][nx][nl][nr][no] = nv;
	  q.push( {nv,ny,nx,nl,nr,no} );
	}
      }

      if(y+1<h){
	int nx = x, ny = y+1, nl = x, nr = x, no = o-1, nv = v;
	if(c[ny][nx] > 0){
	  no = min(m, no+c[ny][nx]);
	}else{
	  nv -= c[ny][nx];
	}

	if(d[ny][nx][nl][nr][no] < 0 || d[ny][nx][nl][nr][no] > nv){
	  d[ny][nx][nl][nr][no] = nv;
	  q.push( {nv,ny,nx,nl,nr,no} );
	}
      }
    }

    if(ans > f){
      cout << "NA" << endl;
    }else{
      cout << ans << endl;
    }
  }
}
accuracy: 1
time_ms: 10
memory_kb: 6712
final_rank: 5

code_snippet: #include<bits/stdc++.h>
using namespace std;

const int INF=1001001001;

int W,H,F,M,O;
int fld[15][15];

struct data{
    int y,x,s,o,f;
    data(int y,int x,int s,int o,int f)
        :y(y),x(x),s(s),o(o),f(f){}

    bool operator<(const data &d)const{
        return f>d.f;
    }
};

int dist[15][15][1<<10][50];

void solve(){
    fill_n(***dist,15*15*(1<<10)*50,INF);
    priority_queue<data>que;
    for(int i=0;i<W;i++){
        dist[0][i][1<<i][O]=0;
        que.push(data(0,i,1<<i,O,0));
    }

    while(que.size()){
        data d=que.top();que.pop();
        if(dist[d.y][d.x][d.s][d.o]<d.f)continue;
        if(d.o==0)continue;
        for(int i=-1;i<=1;i+=2){
            int ny=d.y,nx=d.x+i;
            if(nx<0||nx>=W)continue;
            int ns,no,nf;
            if(d.s>>nx&1){
                ns=d.s;no=d.o-1;nf=d.f;
            }
            else{
                ns=d.s|(1<<nx);
                no=min(M,d.o-1+(fld[ny][nx]>=0?fld[ny][nx]:0));
                nf=d.f+(fld[ny][nx]>=0?0:-fld[ny][nx]);
            }
            if(no<0)continue;
            if(dist[ny][nx][ns][no]<=nf)continue;
            dist[ny][nx][ns][no]=nf;
            que.push(data(ny,nx,ns,no,nf));
        }

        int ny=d.y+1,nx=d.x;
        if(ny>H)continue;
        int ns,no,nf;
        ns=1<<nx;
        no=min(M,d.o-1+(fld[ny][nx]>=0?fld[ny][nx]:0));
        nf=d.f+(fld[ny][nx]>=0?0:-fld[ny][nx]);
        if(no<0)continue;
        if(dist[ny][nx][ns][no]<=nf)continue;
        dist[ny][nx][ns][no]=nf;
        que.push(data(ny,nx,ns,no,nf));
    }

    int mi=INF;
    for(int j=0;j<W;j++){
        for(int o=0;o<=M;o++){
            mi=min(mi,dist[H][j][1<<j][o]);
        }
    }

    if(mi>F)cout<<"NA"<<endl;
    else cout<<mi<<endl;
}

int main(){
    while(cin>>W>>H,W||H){
        cin>>F>>M>>O;M--;O--;
        for(int i=1;i<=H;i++){
            for(int j=0;j<W;j++){
                cin>>fld[i][j];
            }
        }
        solve();
    }
    return 0;
}
accuracy: 1
time_ms: 210
memory_kb: 46328
final_rank: 19

code_snippet: #include<bits/stdc++.h>
using namespace std;
#define pb push_back
#define fr first
#define sc second
typedef pair<int, int> Pii;
typedef pair<int, Pii> Pip;
typedef vector<int> Vi;
const int INF = (1<<25);
const int MAX_V = 101;
const int dx[]={1,0,-1,0}, dy[]={0,-1,0,1};

int w, h, f, m;
int c[10][10];

struct State {
  int x, y, l, r, oxy, cost;
  State(int x_, int y_, int l_, int r_, int oxy_, int cost_) {
    x=x_; y=y_; l=l_; r=r_; oxy=oxy_; cost=cost_;
  }
  State(){}
};

bool operator<(const State& a, const State& b) {
  return a.cost > b.cost;
}

int d[10][10][10][10][51];

int solve(int o) {
  if( o < 2 ) return INF;

  for(int y=0; y<10; y++) {
    for(int x=0; x<10; x++) {
      for(int l=0; l<10; l++) {
	for(int r=0; r<10; r++) {
	  for(int m=0; m<51; m++) {
	    d[y][x][l][r][m] = INF;
	  }
	}
      }
    }
  }

  priority_queue<State> q;
  for(int x=0; x<w; x++) {
    int cost = -1 * min(c[0][x], 0);
    int oxy = min(m, o - 1 + max(c[0][x], 0));
    d[0][x][x][x][oxy] = cost;
    q.push(State(x, 0, x, x, oxy, cost));
  }

  int res = INF;
  while( !q.empty() ) {
    State p = q.top(); q.pop();
    int x = p.x, y = p.y, l = p.l, r = p.r;
    int oxy = p.oxy, cost = d[y][x][l][r][oxy];

    if( oxy == 0 ) continue;
    if( f < cost ) return INF;
    if( y == h-1 ) {
      res = cost; 
      break;
    }
    if( oxy == 1 ) continue;

    for(int dx=-1; dx<=1; dx+=2) {
      int mx = x + dx;
      if( mx < 0 || w <= mx ) continue;

      int l_ = min(l, mx), r_ = max(r, mx);
      int next_cost = cost, next_oxy;
      if( l_ == l && r_ == r ) {
	next_oxy = oxy -1;
      }
      else {
	next_cost += -1 * min(c[y][mx], 0);
	next_oxy = min(m, oxy - 1 + max(c[y][mx], 0));
      }
      if( next_cost < d[y][mx][l_][r_][next_oxy] ) {
	d[y][mx][l_][r_][next_oxy] = next_cost;
	q.push(State(mx, y, l_, r_, next_oxy, next_cost));
      }
    }

    if( y < h-1 ) {
      int next_cost = cost + -1 * min(c[y+1][x], 0);
      int next_oxy = min(m, oxy - 1 + max(c[y+1][x], 0));
      if( next_cost < d[y+1][x][x][x][next_oxy] ) {
	d[y+1][x][x][x][next_oxy] = next_cost;
	q.push(State(x, y+1, x, x, next_oxy, next_cost));
      }
    }
  }
  if( f < res ) return INF;
  return res;
}

int main() {
  while( cin >> w >> h, w || h ) {
    int o;
    cin >> f >> m >> o;
    for(int y=0; y<h; y++) {
      for(int x=0; x<w; x++) {
	cin >> c[y][x];
      }
    }

    int ans = solve(o);
    if( ans == INF ) cout << "NA" << endl;
    else cout << ans << endl;
  }
}
accuracy: 1
time_ms: 10
memory_kb: 3324
final_rank: 3

code_snippet: #include<bits/stdc++.h>
using namespace std;
const long long INF = 1LL << 60;
typedef long long int64;

int W, H;
int f, m, o;
int c[10][10];

int64 dp[10][10][51][1 << 10];
int64 rec(int x, int y, int air, int dig)
{
  if(x < 0 || x >= W || air <= 0) return(INF);
  if(y + 1 == H) return(max(0, -c[y][x]));
  air = min(m, air + max(0, c[y][x]) * (1 - ((dig >> x) & 1)));
  if(~dp[x][y][air][dig]) return(dp[x][y][air][dig]);
  int64 ret = INF;
  ret = min(ret, rec(x - 1, y, air - 1, dig|(1 << x)));
  ret = min(ret, rec(x + 1, y, air - 1, dig|(1 << x)));
  ret = min(ret, rec(x, y + 1, air - 1, 0));
  return(dp[x][y][air][dig] = min< long long >(INF, ret + (1 - ((dig >> x) & 1)) * max(0, -c[y][x])));
}
main()
{
  while(cin >> W >> H, W) {
    fill_n(***dp, 10 * 10 * 51 * (1 << 10), -1);
    cin >> f >> m >> o;
    for(int i = 0; i < H; i++) {
      for(int j = 0; j < W; j++) {
        cin >> c[i][j];
      }
    }
    int64 ret = INF;
    for(int i = 0; i < W; i++) {
      ret = min(ret, rec(i, 0, o - 1, 0));
    }
    if(ret > f) cout << "NA" << endl;
    else cout << ret << endl;
  }
}
accuracy: 1
time_ms: 180
memory_kb: 41996
final_rank: 18

code_snippet: #include<iostream>
#include<vector>
#include<algorithm>
#include<queue>
#include<set>
#include<map>
#include<cstring>
#include<string>
#include<sstream>
#include<complex>
#include<tuple>
#include<cassert>
using namespace std;

#define reep(i, s, n) for(int i=s;i<(int)n;i++)
#define rep(i, n) for(int i=0;i<(int)n;i++)
#define REP(i, n) for(int i=0;i<(int)n;i++)
#define all(v) v.begin(), v.end()
#define tyd typedef
#define vc vector
#define pb push_Back
#define eb emplace_back
#define mp make_pair

typedef long long ll;
typedef vector<int> vi;
typedef vector<vi> vvi;
typedef pair<int, int> pii;
const int IINF = 1<<28;

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

int field[16][16];
int h, w;
int f, m, o;

struct Node{
	int x, y, cost, oxy, v;
	Node( int x, int y, int cost, int oxy, int v)
		:x(x), y(y), cost(cost), oxy(oxy), v(v)
	{}

	friend bool operator < ( const Node& n1, const Node& n2 )
	{
		return n1.cost > n2.cost;
	}
};

bool visited[15][15][55][2054];
int dijkstra (){
	priority_queue<Node> que;
	if(o == 1) return IINF;
	rep(i, w){
		int cost = 0, oxy = o;
		if( field[0][i] < 0 ){
			cost += -field[0][i];
		}else{
			oxy += field[0][i];
		}
		que.emplace(i, 0, cost, min(oxy - 1, m), 1 << i);

	}

	memset(visited, 0, sizeof(visited));

	int ret = IINF;
	while( !que.empty() ){
		Node n = que.top();
		que.pop();
		if(n.oxy <= 0) continue;
		if( n.cost > f ){
			break;
		}
		if( n.y == h-1 ){
			if( n.oxy > 0 ){
				return n.cost;
			}else{
				continue;
			}
		}
		if( visited[n.y][n.x][n.oxy][n.v] ){
			continue;
		}
		visited[n.y][n.x][n.oxy][n.v] = true;
		if(n.oxy <= 1) continue;
		rep(i, 3){
			int nx = n.x + dx[i];
			int ny = n.y + dy[i];
			int nv = n.v;
			if( nx < 0 || nx >= w ){
				continue;
			}
			if(ny != n.y) nv = 0;
			int cost = n.cost;
			int oxy = n.oxy - 1;
			
			if((nv & (1<<nx)) == 0){
				if( field[ny][nx] > 0 ){
					oxy += field[ny][nx];
				}
				else{
					cost += -field[ny][nx];
				}
			}
			que.emplace(nx, ny, cost, min(oxy, m), nv | (1 << nx));
		}
	}

	return ret;
}

int main(){
	while(cin >> w >> h) {
		if(!w && !h) break;
		cin >> f >> m >> o;
		rep(i, h) {
			rep(j, w) {
				cin >> field[i][j];
			}
		}

		int ans = IINF;
		ans = min(ans, dijkstra());
		if( ans == IINF || ans > f ){
			cout << "NA" << endl;
		}
		else{
			cout << ans << endl;
		}
	}
	return 0;
}
accuracy: 1
time_ms: 50
memory_kb: 26232
final_rank: 16