题意
有
n
n
棵摇钱树,一开始第 棵树上有
ai
a
i
个硬币,每过一天将长出
bi
b
i
个硬币。问
m
m
天,每天不间断的砍一棵树,最多能获得多少硬币?
思路
长硬币快的树肯定较晚的砍去,根据这个可以把树先按 b b <script type="math/tex" id="MathJax-Element-41">b</script> 值从小到大排序,然后由于砍树不间断,可以把时间看作费用,把再这个时间砍可获得的硬币数看作价值进行01背包。可见,对于较一般的01背包题目,只要认清物品,选好费用和价值,写好转移式即可。
代码
#include<iostream>
#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#define FOR(i,x,y) for(int i=(x);i<=(y);i++)
#define DOR(i,x,y) for(int i=(x);i>=(y);i--)
#define tomax(a,b) (a=max(a,b))
typedef long long LL;
using namespace std;
int dp[253];
struct Tree
{
int a,b;
bool operator <(const Tree &_)const
{
return b<_.b;
}
int cut(int day){return a+b*(day-1);}
}t[253];
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
int n,m,ans=0;
memset(dp,0,sizeof(dp));
scanf("%d%d",&m,&n);
FOR(i,1,m)scanf("%d",&t[i].a);
FOR(i,1,m)scanf("%d",&t[i].b);
sort(t+1,t+1+m);
FOR(i,1,m)
DOR(j,n,1)
tomax(ans,tomax(dp[j],dp[j-1]+t[i].cut(j)));
printf("%d\n",ans);
}
return 0;
}