hdu 4600 Harvest Moon

模拟,wa了很多次,注意用int64

方法:枚举选择的种子并进行模拟。由于只能选择一种种子,模拟时每次选择最大的空地进行播种 即可。需要稍微注意的是,如果从左上角开始种植 3 * 3 的完整方格,种完之后应当首先考 虑右下角的 3 * 3 方格,它拥有当前非完整 3 * 3 的最大的面积,随后再考虑最右和最下的带 状面积。 

#include<iostream>
#include<vector>
#include<algorithm>
#include<cstdio>
#include<queue>
#include<stack>
#include<string>
#include<map>
#include<set>
#include<cmath>
#include<cassert>
#include<cstring>
#include<iomanip>
using namespace std;
typedef long long  int i64;
/************ for topcoder by zz1215 *******************/
#define foreach(c,itr)  for(__typeof((c).begin()) itr=(c).begin();itr!=(c).end();itr++)
#define FOR(i,a,b)      for( int i = (a) ; i <= (b) ; i ++)
#define FF(i,a)         for( int i = 0 ; i < (a) ; i ++)
#define FFD(i,a,b)      for( int i = (a) ; i >= (b) ; i --)
#define S64(a)          scanf(in64,&a)
#define SS(a)           scanf("%d",&a)
#define LL(a)           ((a)<<1)
#define RR(a)           (((a)<<1)+1)
#define pb              push_back
#define pf              push_front
#define X               first
#define Y               second
#define CL(Q)           while(!Q.empty())Q.pop()
#define MM(name,what)   memset(name,what,sizeof(name))
#define MC(a,b)        memcpy(a,b,sizeof(b))
#define MAX(a,b)        ((a)>(b)?(a):(b))
#define MIN(a,b)        ((a)<(b)?(a):(b))
#define read            freopen("out.txt","r",stdin)
#define write           freopen("out1.txt","w",stdout)

const int inf = 0x3f3f3f3f;
const i64 inf64 = 0x3f3f3f3f3f3f3f3fLL;
const double oo = 10e9;
const double eps = 10e-9;
const double pi = acos(-1.0);
const int maxn = 1111;

int w,h,a,d;
i64 y;
int q[maxn];
int p[maxn];
int n[maxn];
int m[maxn];

int grid[10];
int rest[10];
int have[maxn];

i64 gao(i64 money,int x)
{
    i64 re = 0;
    i64 now,temp;
    for(int i=9;i>=1;i--)
    {
    	if(!rest[i]) continue;
        if(p[x]*i>q[x])
        {
            now = money / q[x];
            if(rest[i]<now) now = rest[i];
            money -= now*q[x];                
            re += now*p[x]*i;
        }
    }
    re+=money;
    return re;
}

bool can(int x,int day,int num)
{    
	if(d+1-day - n[x]>=0)
    if( ((d+1-day-n[x])/m[x] + 1) * p[x] * num - q[x] > 0 )
    {
        return true;        
    } 
    return false;
}

i64 work(i64 money,int x,int day)
{
	if(day+n[x]>d+1) return money;
    i64 now,tmep;
    for(int i=9;i>=1;i--)
    {
        if(rest[i] && can(x,day,i))
        {
            now = money/q[x];
        	if(rest[i]<now) now = rest[i];
            rest[i] -= now;
            money -= now*q[x];
            if(day+n[x]<=d+1)
            have[day+n[x]] += now*i;
        }
    }
    return money;
}

i64 get(int x)
{    
    for(int i=1;i<=d+1;i++) have[i] = 0;
    MM(grid,0);
    MM(rest,0);

    int wr = w%3;
    int hr = h%3;
    grid[9] = (w/3)*(h/3);
    grid[wr*3 + hr*(3-wr)] += 1;
    grid[wr*3] += h/3-1;
    grid[hr*3] += w/3-1;
    grid[hr*wr] += 2;

    for(int i=1;i<10;i++)
    {
        rest[i] = grid[i];
    }

    i64 money = y;
    if(m[x] == 0)
    {
        for(int i=1;;)
        {
            if(i+n[x]-1<=d)
            {
                money = gao(money,x);                
                i+=n[x];
            }            
            else
        	{
        		break;
            }
        }        
        return money;
    }
    else
    {
		money = work(money,x,1); 
        for(int i=1;i<=d+1;i++)
        {
        	if(!have[i]) continue;
            money += have[i]*p[x];
            if(i+m[x]<=d+1)
            have[i+m[x]] += have[i];
            money = work(money,x,i);             
        }
        return money;
    }
}

i64 start()
{
    i64 ans = 0;
    for(int i=1;i<=a;i++)
    {
        i64 temp = get(i);
        if(temp>ans)
        {
            ans = temp;            
        }
    }    
    return ans;
}

int main()
{
    int T;
    cin>>T;
    while(T--)
    {
        scanf("%d%d%d%d%I64d", &w, &h, &a, &d, &y);  
        for(int i = 1; i <= a; i++) scanf("%d%d%d%d", &q[i], &p[i], &n[i], &m[i]);             
        cout<<start()<<endl;
    }
    return 0;            
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值