科技庄园(动规练习题)

题目背景

Life种了一块田,里面种了有一些桃树。

Life对PFT说:“我给你一定的时间去摘桃,你必须在规定的时间之内回到我面前,否则你摘的桃都要归我吃!”

PFT思考了一会,最终答应了!

由于PFT的数学不好!它并不知道怎样才能在规定的时间获得最大的价值,

由于PFT不是机器人,所以他的体力并不是无限的,他不想摘很多的桃以至体力为0,而白白把桃给Life。同时PFT每次只能摘一棵桃树,,每棵桃树都可以摘K次(对于同一棵桃每次摘的桃数相同)。每次摘完后都要返回出发点(PFT一次拿不了很多)即Life的所在地(0,0){试验田左上角的桃坐标是(1,1)}。

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

题目描述

输入输出格式

输入格式:

第一行:四个数为N,M,TI,A 分别表示试验田的长和宽,Life给PFT的时间,和PFT的体力。

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

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

输出格式:

一个数:PFT可以获得的最大的桃个数。

样例输入:

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


代码(C++)

#include<cstdio>
#define sr c=getchar()  
#define input read()  
#define pd (c<'0'||c>'9')  
#define fk f=f*10+c-48  
#define ps if (c=='-') d=-1  
using namespace std;
int f[10001];int n,m,zl;int a,g,c,d;
int jz[101][101];
struct node{
	int w,s,p;
}wyc[10001];//w为距离,s为可以摘的次数,p为价值
int max(int x,int y)//最大值
{
	return x>y?x:y;
}
int min(int x,int y)//最小值
{
	return x<y?x:y;
}
int read()//输入优化
{
	char c;int d=1,f=0;
	while (sr,pd) ps; fk;
	while (sr,!pd) fk;
	return d*f;
}
void write(int x)//输出优化
{
	if (!x) return;
	write(x/10);
	putchar(x%10+48);
}
void LRZ()
{
	n=input;m=input;zl=input;a=input;zl=min(zl,a-1);//每走一步消耗一个体力和时间,所以其实是同步的,就可以把它降低为一维费用了。a-1是因为他不想体力为0
	for (int i=1;i<=n;i++)
	 for (int j=1;j<=m;j++)
	  jz[i][j]=input;//输入矩阵的值
	for (int i=1;i<=n;i++)
	 for (int j=1;j<=m;j++)
	  {
	  	a=input;
	  	if (a)
	  	{
	  		g++;
	  		wyc[g].p=jz[i][j];//取价值
	  		wyc[g].w=(i+j)*2;//取距离
	  		wyc[g].s=a;//取可以摘的次数
	  	}
	  }
}
void work()
{
	for (int i=1;i<=g;i++)
	 for (int j=zl;j>=0;j--)
	   for (int k=1;k<=wyc[i].s;k++)//多重背包
	    if(j-k*wyc[i].w>=0)
	    f[j]=max(f[j],f[j-k*wyc[i].w]+k*wyc[i].p);
}
int main()
{
	LRZ();
	work();
	if (!f[zl]) printf("0");else
	write(f[zl]);//输出
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值