您的位置:首页 > 其它

UVA - 10913 Walking on a Grid DAG路径最大值

2014-11-23 09:19 302 查看
题目大意:给出一个矩阵,要求求出从(1,1)走到(n,n)这个位置的路途上的数字的最大和,走的时候有限制,同一个位置不能走两次,有三个移动方向,下,左,右,还有一个限制,给出一个k,要求走过位置是负数的不能超过k

解题思路一:用一个四维数组来表示状态,dp[i][j][k][l]表示(i,j)位置,走了k个负数位置,移动方向是l

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define LL long long
#define maxn 80
#define MIN -((LL)1<<60)
int  N,K;
int mov[3][2] = {{0,1},{1,0},{0,-1}};
bool vis[maxn][maxn][7][3],vis2[maxn][maxn];
long long dp[maxn][maxn][7][3],arr[maxn][maxn];

bool check(int x,int y) {
	return x >= 1 && x <= N && y >= 1 && y <= N;
}

long long solve(int x, int y, int z, int r) {

	bool &flag = vis[x][y][z][r];
	long long &res = dp[x][y][z][r];
	if(flag)
		return res;
	else if( (x == N && y == N) || z == 0) {
		flag = 1;
		if(z == 0)
			res = MIN;
		else
			res = arr[x][y];
		return res;
	}
	else {
		res = MIN;
		for(int i = 0; i < 3; i++) {
			int xx = x + mov[i][0];
			int yy = y + mov[i][1];	
			int t = 0;
			if(arr[x][y] < 0)
				t = - 1;
			if(check(xx,yy) && !vis2[xx][yy]) {
				if((r == 0 && i == 2) || (r == 2 && i == 0))
					continue;
				vis2[xx][yy] = 1;
				long long temp = solve(xx,yy,z+t,i);
				if(temp != MIN) 
					res = max(res,temp+arr[x][y]);	
				vis2[xx][yy] = 0;	
			}
		}
		flag = 1; 
		return res;
	}
}

int main() {
	int mark = 1;
	while(scanf("%d%d",&N,&K) != EOF && N+K) {

		for(int i = 1; i <= N; i++)
			for(int j = 1; j <= N; j++)
				scanf("%lld", &arr[i][j]);

		if(arr

 < 0)
			K--;

		memset(vis,0,sizeof(vis));
		memset(vis2,0,sizeof(vis2));

		long long res = solve(1,1,K+1,1);
		if(res != MIN)
			printf("Case %d: %lld\n",mark++,res);
		else
			printf("Case %d: impossible\n",mark++);
	}
	return 0;
}


解法二:从上往下扫描,然后分别从左往右扫描每一行和从右往左扫描每一行,并进行比较,取最大值

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define maxn 80
#define MIN -0x3f3f3f3f
int N,k;
int arr[maxn][maxn];
int dp[maxn][maxn][maxn],left[maxn][maxn],right[maxn][maxn];

void solve() {

	for(int i = 0 ; i <= k; i++)
		for(int j = 1; j <= N; j++)
			for(int l = 1; l <= N; l++)
				dp[i][j][l] = MIN;
	if(arr[1][1] >= 0)
		dp[0][1][1] = arr[1][1];
	else
		dp[1][1][1] = arr[1][1];

	for(int i = 0; i <= k; i++)
		for(int j = 1; j < N; j++)
			if(dp[i][1][j] != MIN) {
				if(arr[1][j+1] < 0) {
					if(dp[i][1][j] + arr[1][j + 1] > dp[i+1][1][j+1])	
						dp[i+1][1][j+1] = dp[i][1][j] + arr[1][j+1];
				}
				else if (dp[i][1][j] + arr[1][j+1] > dp[i][1][j+1])
					dp[i][1][j+1] = dp[i][1][j] + arr[1][j+1];
			}

	for(int l = 2; l <= N; l++) {

		for(int i = 0; i <= k; i++)
			for(int j = 1; j <= N; j++)	
				if(dp[i][l-1][j] != MIN) {
					if(arr[l][j] < 0) {
						if(dp[i][l-1][j] + arr[l][j] > dp[i+1][l][j])
							dp[i+1][l][j] = dp[i][l-1][j] + arr[l][j];		
					}
					else if(dp[i][l-1][j] + arr[l][j] > dp[i][l][j])
						dp[i][l][j] = dp[i][l-1][j] + arr[l][j];	
				}

		for(int i = 0; i <= k; i++)
			for(int j = 1; j <= N; j++)
				left[i][j] = right[i][j] = dp[i][l][j] ;
	
		for(int i = 0; i <= k; i++)
			for(int j = 1; j < N; j++)
				if(left[i][j] != MIN) {
					if(arr[l][j+1] < 0) {
						if(left[i][j] + arr[l][j+1] > left[i+1][j+1])
							left[i+1][j+1] = left[i][j] + arr[l][j+1];
					}
					else if (left[i][j] + arr[l][j+1] > left[i][j+1])
						left[i][j+1] = left[i][j] + arr[l][j+1];
				}	
		for(int i = 0; i <= k; i++)
			for(int j = N; j > 1; j--)
				if(right[i][j] != MIN) {
					if(arr[l][j-1] < 0) {
						if(right[i][j] + arr[l][j-1] > right[i+1][j-1])
							right[i+1][j-1] = right[i][j] + arr[l][j-1];
					}
					else if (right[i][j] + arr[l][j-1] > right[i][j-1])
						right[i][j-1] = right[i][j] + arr[l][j-1];
				}	
	
		for(int i = 0 ; i <= k; i++)
			for(int j = 1; j <= N; j++)
				dp[i][l][j] = left[i][j] > right[i][j] ? left[i][j] :right[i][j];
	}
}

int main() {
	int mark = 1;
	while(scanf("%d%d",&N,&k) != EOF && N+k) { 
		for(int i = 1; i <= N; i++) 
			for(int j = 1; j <= N; j++)
				scanf("%d",&arr[i][j]); 
			
		solve();
		int max = MIN;
		for(int i = 0; i <= k; i++)
			if(dp[i]

 > max)
				max = dp[i]

;
		if(max != MIN)
			printf("Case %d: %d\n",mark++,max);
		else
			printf("Case %d: impossible\n",mark++);
	}
	return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: