码迷,mamicode.com
首页 > 其他好文 > 详细

UVA - 10913Walking on a Grid(记忆化搜索)

时间:2014-08-13 01:16:55      阅读:222      评论:0      收藏:0      [点我收藏+]

标签:blog   http   os   io   for   ar   2014   cti   

题目:Walking on a Grid


题目大意:给出N * N的矩阵,每个格子里都有一个值,现在要求从(1,1)走到(n, n),只能往下,左,右这三个方向走,并且要求最多只能取k个负数,求这样的要求下能得到的走过格子的值之和最大。


解题思路:记忆化搜索,但是这里要四维的,因为要记录方向,为了防止走回头的路,并且取了几个负数也要记录。然后就是dfs了。状态转移方程:dp【x】【y】【d】【k】 = dp【x + dir【i】【0】】【y + dir【i】【1】】【i】【k1] + G[x][y]; d代表从(x, y)出发走的方向。k:负数的个数(包括x,y这个格子走过的格子的负数总数),k1要根据G【x + dir【i】【0】】【y + dir【i】【1】】】来定,为正就还是等于k,为负就等于k  + 1;

发现初始化真心要小心。


代码:

#include <cstdio>
#include <cstring>

typedef long long ll;

const int N = 80;
const int M = 3;
const ll INF = 0x3f3f3f3f3f; 
const int dir[M][2] = {{0, -1}, {1, 0}, {0, 1}};

int G[N][N];
ll dp[N][N][6][M];
int n, k;

ll Max (const ll a, const ll b) { return a > b ? a: b;}

void init () {

	for (int i = 0; i < n; i++)
		for (int j = 0; j < n; j++)
			for (int l = 0; l <= k; l++)
				for (int m = 0; m < M; m++)
					dp[i][j][l][m] = -INF;

	if (G[0][0] < 0)//一开始的(0,0)位置的值如果是负数的话,那么取负数的机会就被占用了一个。
		k--;
	for (int l = 0; l <= k; l++)
		for (int m = 0; m < M; m++)
			dp[n - 1][n - 1][l][m] = G[n - 1][n - 1];
}

ll DP (int x, int y, int d, int cnt) {

	int newx, newy;
	ll &ans = dp[x][y][cnt][d];
	if (ans != -INF)
		return ans;

	ll temp;
	if (d == 1) {//取下的话,那么三个方向都是可以取的

		for (int i = 0; i < M; i++) {
	
			newx = x + dir[i][0];
			newy = y + dir[i][1];
			if (newx < 0 || newx >= n || newy < 0 || newy >= n)
				continue;

			if (G[newx][newy] < 0 && cnt == k)
				continue;
			if (G[newx][newy] < 0 && cnt < k) {
				temp = DP(newx, newy, 2 - i, cnt + 1); 
				if (temp != -INF - 1)
					ans = Max (ans, temp + G[x][y]); 
			}
			if (G[newx][newy] >= 0) {
				temp = DP (newx, newy, 2 - i, cnt);
				if (temp != -INF - 1)
					ans = Max (ans, temp + G[x][y]);
			}
		}
	} else {//取左/右的话下次就不要取右/左。

		for (int i = (d + 1) % M; i != d; i = (i + 1) % M) {

			newx = x + dir[i][0];
			newy = y + dir[i][1];
			if (newx < 0 || newx >= n || newy < 0 || newy >= n)
				continue;

			if (G[newx][newy] < 0 && cnt == k)
				continue;
			if (G[newx][newy] < 0 && cnt < k) {
				temp = DP(newx, newy, 2 - i, cnt + 1); 
				if (temp != -INF - 1)
					ans = Max (ans, temp + G[x][y]); 
			}
			if (G[newx][newy] >= 0) {
				temp = DP (newx, newy, 2 - i, cnt);
				if (temp != -INF - 1)//当这个位置可以到的时候才计算
					ans = Max (ans, temp + G[x][y]);
			}
		}
	}

	if (ans == -INF)//代表以目前的要求不能到达这个格子
		ans = -INF - 1;
	return ans;
}

int main () {

	int cas = 0;
	while (scanf ("%d%d", &n, &k), n || k) {

		for (int i = 0; i < n; i++)
			for (int j = 0; j < n; j++)
				scanf ("%d", &G[i][j]);

		init ();

		ll ans; 
		ans = DP(0, 0, 1, 0);

		printf ("Case %d:", ++cas);
		if (ans == -INF - 1)
			printf (" impossible\n");
		else
			printf (" %lld\n", ans);		
	}
	return 0;
}


UVA - 10913Walking on a Grid(记忆化搜索),布布扣,bubuko.com

UVA - 10913Walking on a Grid(记忆化搜索)

标签:blog   http   os   io   for   ar   2014   cti   

原文地址:http://blog.csdn.net/u012997373/article/details/38523375

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!