noip2012提高组模拟题樱桃庄园

本题是一个动态规划背包问题。

题目如下:

  

【问题描述】

高考结束啦!结束啦!高考结束第一天,大黑带着她的宠物——麻婆来到一个樱桃园,他们要来摘樱桃吃啦。

这时大黑对他的宠物麻婆说:“你想不想吃樱桃啊?”

麻婆兴奋地说:“好啊!”

大黑说:“好吧,你去摘吧,我掏钱!但是我只给你一定的时间,你必须在规定的时间内回到我面前,否则你摘的樱桃都要归我吃!”

麻婆思考了一会儿,最终答应了。

由于麻婆的数学太弱……他并不知道怎样才能在规定时间摘到最多的樱桃,但你是一个好心人,如果你帮助它,你的RP一定会暴涨的!

对于这个可以RP暴涨的机会,你一定不会错过的是不是?

由于麻婆不是机器人,所以它的体力并不是无限的,他不想摘很多的樱桃以至体力为0,而白白把樱桃让给大黑。樱桃园呈长方形,每棵樱桃树都有自己唯一的坐标,樱桃园左上角的樱桃树坐标是(1,1)。麻婆每次只能摘一棵樱桃树,每颗樱桃树都可以摘K次(对于同一棵樱桃树,每次采摘所得樱桃数目相同)。每次摘完后都要返回出发点即大黑的所在地(0,0)

麻婆每秒只能移动一个单位,每移动一个单位耗费体力1(只限上下左右移动,摘取不花费时间和体力)。

【输入】

第一行共四个数,为N,M,TI,A分别表示试验田的长和宽,大黑给麻婆的时间,和麻婆的体力。

下面一个N行M列的矩阵樱桃园。表示每次每棵樱桃树上能摘的樱桃数。

接下来N行M列的矩阵,表示每棵樱桃树最多可以采摘的次数K 

【输出】

一个数:麻婆可以获得的最多的樱桃个数。

【输入输出样例】

4 4 13 20
10 0 0 0
0 0 10 0
0 0 10 0
0 0 0 0
1 0 0 0
0 0 2 0
0 0 4 0
0 0 0 0


输出:10


10<=30%<=50

10<=100%<=100

对于K,10<=100%<=100

保证结果在longint范围内


#include
#include
#include
#include
#include
#include
using namespace std;
int n,m,t,a;
int f[1000005],k(0);
int maps[105][105],kmaps[105][105],v[1000005],dis[1000005],maxx(0);
int main()
{
	freopen("manor.in","r",stdin);
	freopen("manor.out","w",stdout);
	scanf("%d %d %d %d",&n,&m,&t,&a);
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=m;j++)
		{
			scanf("%d",&maps[i][j]);
		}
	}
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=m;j++)
		{
			scanf("%d",&kmaps[i][j]);
		}
	}
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=m;j++)
		{
			if(maps[i][j]!=0)
			{
			if((i+j)*2<=t)//把“超时”的点去掉
			{
				while(kmaps[i][j]>0)
				{
					k++;
					v[k]=maps[i][j];
					kmaps[i][j]--;
					dis[k]=(i+j)*2;
				}
				
			}
		    }
		}
	}
	for(int i=1;i<=k;i++)
	{
		for(int j=a;j>dis[i];j--)
		f[j]=max(f[j],f[j-dis[i]]+v[i]);
	}

for(int i=1;i<=k;i++)
maxx=max(f[i],maxx);
printf("%d\n",maxx);
	return 0;
}

思路:乍一看好像是一个搜索题目,但仔细阅读,题目中说每次采摘都要回去,而且根据数据范围来看搜索会超时,所以想到了DP的背包。

    经过转化,可以转化成01背包(应该是吧,动态转移方程使用的01背包的,但我同学说是多重背包),这个题就过了!

本人的C++水平还不是很高,难免有错误和漏洞,请各位斧正!



你可能感兴趣的:(C++类)