【9922】科技庄园

Time Limit: 1 second
Memory Limit: 128 MB

【问题描述】

Life种了一块田,里面种了有一些桃树。
Life对PFT说:“我给你一定的时间去摘桃,你必须在规定的时间之内回到我面前,否则你摘的桃都要归我吃!”
PFT思考了一会,最终答应了!
由于PFT的数学不好!它并不知道怎样才能在规定的时间获得最大的价值,
由于PFT不是机器人,所以他的体力并不是无限的,他不想摘很多的桃以至体力为0,而白白把桃给Life。同时PFT每次只能摘一棵桃
树,每颗桃树都可以摘K次(对于同一棵桃每次摘的桃树相同)。每次摘完后都要返回出发点(PFT一次拿不了很多)即LIfe的所
在地(0,0){试验田左上角的桃坐标是(1,1)} 。
PFT每秒只能移动一个单位,每移动一个单位消耗体力1(摘取不花费时间和体力,但只限上下左右移动)。
样例解释

数据范围
对于 M N TI A,10≤30%≤50,10≤100%≤100
对于K,10≤100%≤100
保证结果在longint

【输入格式】

第一行 :四个数为N,M,T1,A分别表示试验田的长和宽,LIFE给PFT的时间,和PFT的体力。
下面一个N行M列的矩阵桃田。表示每次每颗桃树上能摘的桃树。
接下来N行M列的矩阵,表示每颗桃最多可以采摘的次数K。

【输出格式】

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

Sample Input

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



Sample Output

10

【题解】
这是一道背包问题。到某个地方去摘桃子所花费的时间和体力是固定的。但是有一个坑点。
题目写到体力值最后不能为0.也就是说回到起点后,体力值也不能为0!!!!如果没看到这个会错一半。
把去摘桃子的过程看成是一个物品。然后这个物品可以取k次。k就是第二个矩阵中的数字。
然后就是一个多重背包问题了。
(去摘桃子时花费的体力和时间都是(i+j)*2);
然后一开始把体力--;然后再比较体力和时间。取其中的较小值。作为第二层循环的起点(多重背包要逆序
更新!)
【代码】
#include <cstdio>
#include <cstring>

int n,m,mw1,mw2,ma,map[200][200],map2[200][200],f[200],nn = 0,c[40000],w[40000],num[40000];

void input_data()
{
	scanf("%d%d%d%d",&n,&m,&mw1,&mw2);
	mw2--;
	for (int i = 1;i <= n;i++)
		for (int j = 1;j <= m;j++)
			scanf("%d",&map[i][j]); //输入地图 
	for (int i = 1;i <= n;i++)
		for (int j = 1;j <= m;j++)
			scanf("%d",&map2[i][j]); //输入第二个矩阵 
	for (int i = 1;i <= n;i++)
		for (int j = 1;j <= m;j++) 
			if (map[i][j] > 0) //然后找到那些有桃子的树 置为一个物品。 花费是路程,价值是桃子个数,可以摘几次就能拿几次 
				{
					nn++;
					c[nn] = map[i][j];
					num[nn] = map2[i][j];
					w[nn] = (i+j)*2;	
				}
}

void get_ans()
{
	memset(f,0,sizeof(f)); //初始化f数组 
	ma = mw1;
	if (mw2 < mw1) //取体力-1和时间的较小值。 
		ma = mw2;
	for (int i = 1;i <= nn;i++) //枚举nn个物品 
		for (int j = ma;j >= 0;j--) //因为是多重背包 所以要逆序更新。 
			for (int k = 1;k <= num[i];k++)
				{
					if (j-k*w[i] < 0)  //如果超过了背包容量 则跳过 
						break;
					if (f[j] < f[j-k*w[i]] + k*c[i]) //能更新则更新 
						f[j] = f[j-k*w[i]] + k*c[i];
				}
}

void output_ans()
{
	printf("%d",f[ma]);
}

int main()
{
	//freopen("F:\\rush.txt","r",stdin);
	input_data();
	get_ans();
	output_ans();
	return 0;	
}


转载于:https://www.cnblogs.com/AWCXV/p/7632378.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值