[各种面试题] 棋盘寻宝扩展

题目描述:

现在有一个8*8的棋盘,上面放着64个不同价值的礼物,每个小的棋盘上面放置一个礼物(礼物的价值大于0小于100),一个人初始位置在棋盘的左上角,每次他只能向下或向右移动一步,并拿走对应棋盘上的礼物,结束位置在棋盘的右下角。从棋盘的左上角移动到右下角的时候的,每次他只能向下或向右移动一步,并拿走对应棋盘上的礼物,但是拿到的所有的礼物的价值之和不大于一个限定值limit,请设计一个算法请实现,使其能够获得不超过限制值limit的最大价值的礼物。

输入:

输入包含多个测试用例,每个测试用例共有9行,第一行是一个限制值limit<=1000,下面还有8行8列,第i行的第j列的数字代表了该处棋盘上的礼物的价值,每两个数之间用空格隔开。

输出:

对于每组测试用例,请输出你能够获得不超过限制值limit的最大价值的礼物。若没有符合条件的线路则输出-1。

样例输入:
90
4 2 5 1 3 8 9 7
4 5 2 3 7 1 8 6
7 2 1 8 5 9 3 6
2 8 9 5 6 3 1 7
1 2 4 5 3 7 9 6
3 5 7 8 9 6 2 4
10 8 1 4 7 5 3 9
7 4 6 2 1 3 9 8
样例输出:
90


加个背包就是了,8*8*1000,都不用滚动数组了,这个复杂度直接暴力就轻松hold住了。

注意读题是 如果到不了,那么输出-1,所以要判断如果当前格子的左边和上面两个格子都到不了,那它自己肯定也到不了了,否则再做背包更新。

#include<iostream>
#include<vector>
#include<cstdio>
#include<cstring>
using namespace std;

const int N=8;
int dp[N+1][N+1][1005];
int grid[N+1][N+1];

int main()
{
	memset(dp,0,sizeof(dp));
	int limit;
	while(scanf("%d",&limit)!=EOF)
	{
		for(int i=1;i<=N;i++)
		{
			for(int j=1;j<=N;j++)
			{
				scanf("%d",&grid[i][j]);
				for(int t=0;t<=limit;t++)
					dp[i][j][t]=0;
			}
		}
		for(int i=1;i<=N;i++)
		{
			for(int j=1;j<=N;j++)
			{
				for(int t=0;t<grid[i][j];t++)
					dp[i][j][t]=0;
				for(int t=grid[i][j];t<=limit;t++)
				{
					if(i==1&&j==1)
					{
						dp[i][j][t]=grid[i][j];
						continue;
					}
					if(dp[i-1][j][t-grid[i][j]]==0&&dp[i][j-1][t-grid[i][j]]==0)
						dp[i][j][t]=0;
					else
						dp[i][j][t]=max(dp[i-1][j][t-grid[i][j]],dp[i][j-1][t-grid[i][j]])+grid[i][j];
				}
			}
		}
		int ans =dp[N][N][limit];
		if( ans==0 )
			printf("-1\n");
		else
			printf("%d\n",ans);
	}
}



你可能感兴趣的:([各种面试题] 棋盘寻宝扩展)