hdu 4600 Harvest Moon

贪心+模拟

第一次碰这类题,找大牛们的代码借鉴下

#include <stdio.h>
#include <algorithm>
#include <string.h>
using namespace std;
const int MAXN = 1005;
typedef long long ll;
struct node
{
	int buy, bk, n, m;
}data[MAXN];
int w, h, a, day;
ll coin;
int num[10]; /// n格的方块最多几个
int cpNum[10], next[MAXN], sum[MAXN];
/**
	贪心法,先把连续的3×3矩阵从最左上角开始铺满
	对剩余的区域,先铺最右下角,再铺其他
	x = w%3, y = h%3;
	最右下角: 9 - (3-x)*(3-y) == 3x + 3y - xy > xy 
	因此: 3*3 >= x*3 || y*3 >= 3x + 3y - xy >= xy			 
*/
int top;
/// now-data[h].n时刻买入,计算到结束时的收益, 扩增土地
void bozhong(ll &t_mon, int id, int now)
{
	int tt;
	ll tmp = 0;
	if (now > day) return;
	if (!data[id].m)
		tmp = data[id].bk;
	else
		tmp = (ll)data[id].bk * (ll)(1+(day-now)/data[id].m);
	while (top> 0 && t_mon > 0)
	{
		/// 投入大于收益
		if (top * tmp <= data[id].buy)
		{
			top = -1;break;	
		}
		
		tt = min((ll)cpNum[top], t_mon/data[id].buy); /// 购买数量
		t_mon -= tt * data[id].buy;
		cpNum[top] -= tt;
		next[now] += tt; ///	到now时刻需要播种的份数
		sum[now] += tt * top;	/// 到now时刻可收获的土地块数
		if (cpNum[top] == 0) --top;
		else break;
	}
}
ll solve(int id)
{
	ll res = coin;
	memset(next, 0, sizeof next);
	memset(sum, 0, sizeof sum);
	memcpy(cpNum, num, sizeof num);
	top = 9;
	bozhong(res, id, data[id].n);
	for (int i = 1; i<= day; ++i)
	{
		if (sum[i] == 0) continue;
		/// 收益
		res += sum[i] * data[id].bk;
		/// 在原有基础上继续
		if (data[id].m == 0 && i+data[id].n <= day)
		{
			res -= next[i] * data[id].buy;
			next[i+data[id].n] += next[i];
			sum[i+data[id].n] += sum[i];
		}
		else if (data[id].m != 0 && i+data[id].m <= day)
		{
			sum[i+data[id].m] += sum[i];
		}	
		/// 扩增
		bozhong(res, id, i+data[id].n);
	}
	return res;
}
int main()   
{
#ifndef ONLINE_JUDGE
    freopen("in.txt", "r", stdin);
#endif
	int i, j, t;
	ll res;
	scanf("%d", &t);
	while (t--)
	{
		scanf("%d%d%d%d%lld", &w, &h, &a, &day, &coin);
		for (i = 0; i< a; ++i)
			scanf("%d%d%d%d", &data[i].buy, &data[i].bk, &data[i].n, &data[i].m);
		memset(num, 0, sizeof num);
		num[9] = (w/3)*(h/3);
		int x = w%3, y = h%3;
		num[3*x + 3*y - x*y]++;
		num[x*y] += 2;
		num[3*x] += (h/3)-1;
		num[3*y] += (w/3)-1;
		for (i = 0, res = coin; i< a; ++i)	res = max(res, solve(i));
		printf("%lld\n", res);
	}
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值