P2760

科技庄园

题目背景

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可以获得的最大的桃个数。

样例 #1

样例输入 #1

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

样例输出 #1

10

提示

样例说明:

可以摘到1次(1,1)和1次(2,3),体力和时间不满足再摘桃了。

范围:

对于M,N,TI,A 10<=30%<=50 10<=100%<=100

对于K 10<=100%<=100

保证结果在long int范围内

很容易发现是个多重背包问题
有几个注意点:由于这题我们降维消去了n的那一维
所以多重背包只能用转化成0-1背包的方式(朴素/二进制优化)
所以说转移是 f[w1][w2]=max(f[w1][w2],f[w1-cost1][w2-cost2]+val)
不带k了!(带k的这种写法需要i-1的状态值)
还有次数枚举时是1~k[i] 不能取0!

枚举顺序

i
cnt
w1(倒序)
w2(倒序)

点击查看代码
#include<bits/stdc++.h>
using namespace std;
#define int long long
int n,m,t,w;
struct did{
	int x,y,cost;
}c[105105];
int a[105][105],b[105][105],nn,f[1005][1005];
signed main()
{
	ios::sync_with_stdio(false);
	cin>>n>>m>>t>>w;
	for(int i=1;i<=n;i++)
		for(int j=1;j<=m;j++)
		{
			cin>>a[i][j];
			if(a[i][j]!=0)
			{
				c[++nn].cost=(i+j)*2;
				c[nn].x=i,c[nn].y=j;
			}
		}
	for(int i=1;i<=n;i++)
		for(int j=1;j<=m;j++)
			cin>>b[i][j];
	for(int k=1;k<=nn;k++)
	for(int l=1;l<=b[c[k].x][c[k].y];l++)
	for(int i=t;i>=0;i--)
		for(int j=w;j>=0;j--)
		{
			
				
					if(i-c[k].cost>=0&&j-c[k].cost>=0)
						f[i][j]=max(f[i][j],f[i-c[k].cost][j-c[k].cost]+a[c[k].x][c[k].y]);
		}
	int maxx=0;
	for(int i=1;i<=t;i++)
		for(int j=1;j<w;j++)
			maxx=max(maxx,f[i][j]);
//	cout<<f[t][w-1]<<"\n";
	cout<<maxx<<"\n";
	return 0;
}
posted @ 2023-01-12 22:13  PKU_IMCOMING  阅读(9)  评论(0)    收藏  举报