zoj3211(贪心+dp)

Dream City

Time Limit: 1 Second       Memory Limit: 32768 KB

JAVAMAN is visiting Dream City and he sees a yard of gold coin trees. There are n trees in the yard. Let's call them tree 1, tree 2 ...and tree n. At the first day, each tree ihas ai coins on it (i=1, 2, 3...n). Surprisingly, each tree i can grow bi new coins each day if it is not cut down. From the first day, JAVAMAN can choose to cut down one tree each day to get all the coins on it. Since he can stay in the Dream City for at most m days, he can cut down at most m trees in all and if he decides not to cut one day, he cannot cut any trees later. (In other words, he can only cut down trees for consecutive m or less days from the first day!)

Given nmai and bi (i=1, 2, 3...n), calculate the maximum number of gold coins JAVAMAN can get.

Input

There are multiple test cases. The first line of input contains an integer T (T <= 200) indicates the number of test cases. Then T test cases follow.

Each test case contains 3 lines: The first line of each test case contains 2 positive integers n and m (0 < m <= n <= 250) separated by a space. The second line of each test case contains n positive integers separated by a space, indicating ai. (0 < ai <= 100, i=1, 2, 3...n) The third line of each test case also contains n positive integers separated by a space, indicating bi. (0 < bi <= 100, i=1, 2, 3...n)

Output

For each test case, output the result in a single line.

Sample Input

2
2 1
10 10
1 1
2 2
8 10
2 3

Sample Output

10
21

Hints:
Test case 1: JAVAMAN just cut tree 1 to get 10 gold coins at the first day.
Test case 2: JAVAMAN cut tree 1 at the first day and tree 2 at the second day to get 8 + 10 + 3 = 21 gold coins in all.


题意:一个人在一个城市待m天,这个城市一共有n棵树,一开始都有基值ai,如果不砍每天都会增大bi,人在这m天内必须连续每天砍一棵树,否则如果一天不砍就不能再砍,求能获得的最大值。(n>=m)

思路:一开始一直想不通为什么贪心+dp是正确的,后来想明白了。因为n>=m,所以要在m天内获得最大值,必须要每天都砍树,所以必定是从n棵树中选m棵树来砍。既然已经选定了m棵树接下来就是排序的问题了(谁先砍?),必然是斜率bi小的先砍。所以要贪心地把斜率小的放在前面。所以不管选哪m棵树,必然是斜率小的先砍,这就是要贪心的原因,再dp一下就okay了。

#include<iostream>
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
int n,m;
int dp[255][255];
struct node
{
	int a,b;
}tree[255];
bool cmp(node x,node y)
{
	return x.b<y.b;
}
int main()
{
	int t;
	cin>>t;
	while(t--)
	{
		cin>>n>>m;
		for(int i=1;i<=n;i++)cin>>tree[i].a;
		for(int i=1;i<=n;i++)cin>>tree[i].b;
		//先贪心,斜率小的先砍
		sort(tree+1,tree+n+1,cmp);
		memset(dp,0,sizeof(dp));
		for(int i=1;i<=n;i++)
		{
			for(int j=1;j<=min(i,m);j++)   //因为要连续砍所以 j<=min(i,m)
			{
				//转移方程:j天砍 i-1棵树,第i棵不砍和在第j天砍第i棵树 
				dp[i][j]=max(dp[i-1][j],dp[i-1][j-1]+tree[i].a+tree[i].b*(j-1));
			}
		}
		cout<<dp[n][m]<<endl;
	}
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值