当前位置:编程学习 > C/C++ >>

hdu - 4600 - Harvest Moon

题意:农场游戏,一块w * h的土地,有A种种子可供选择但只可以选择一种,D天的种植时间,一个人有Y的钱。每种(x种)种子,一个种下,种下的格子及周围的8个格子N[x]天后有收获(重叠的格子只算1次),每个小格子卖出去可赚P[x]元,这种种子购入时每个Q[x]元,种子有些可以多次收获,有些不可以,可以多次收获的种子在第N[x]天第一次收获后每隔M[x]天收获一次。问D天后,这人的现金最多是多少(3 ≤ w, h ≤ 100, 0 <A, D ≤ 1000, 0 < Y ≤ 100000, 0 < Q_i, P_i ≤ 1000; N_i, M_i ≤ 10000)。
 
 
——>>传参时类型声明为了int,一直WA无数。。。

按天模拟(可能开始的时候,不够钱买更多的种子,以致有些空地没种子,于是有了收获有钱后并且再购买种子还有得赚则再购入种子)。

#include <cstdio>  
#include <algorithm>  
#include <cstring>  
  
using namespace std;  
  
const int maxn = 1000 + 10;  
const int maxm = 9 + 5;  
  
int w, h, A, D;  
long long Y;  
int Q[maxn], P[maxn], N[maxn], M[maxn];  
int num[maxm];      //num[i]表示9个格子中占了i个有效格子的种子数  
int remain[maxm];       //remain[i]表示在种植了其中的一些种子后,剩余空地中9个格子中占了i个有效格子的种子数  
int harvestGrid[maxn];      //harvestGrid[i]表示i天后有收获的土地格子数  
int blank[maxn];        //blank[i]表示第i天有多少空地可以种植  
int p;      //一个种子,尽量种在占格子尽量多的地方  
int now;        //现在是第几天  
  
void read(){  
    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]);  
}  
  
void init(){  
    memset(num, 0, sizeof(num));  
    num[9] = (w/3) * (h/3);     //左上方  
    int ww = w % 3, hh = h % 3;  
    num[9-(3-ww)*(3-hh)]++;     //右下角  
    num[3*hh] += w/3 - 1;       //左下方  
    num[3*ww] += h/3 - 1;       //右上角  
    num[ww*hh] += 2;        //左下方与右下角中间的部分和右上角与右下角之间的部分  
}  
  
bool isok(int x){       //判断这种种子是否值得购买  
    if(!M[x]) return (long long)P[x] * p > Q[x] ? 1 : 0;      //时间要够,要能赚钱  
    else return (long long)(1 + (D - now - N[x]) / M[x]) * p * P[x] > Q[x] ? 1 : 0;        //时间不够的话求出的是非正数,一样可以判  
}  
  
long long work(int x, long long money){  
    if(D - now < N[x]) return money;        //时间不够,直接返回  
    while(p >= 1){  
        if(!isok(x)){       //看看是否应该买种子  
            p = 0;      //没有收获的话,不用再往下扫描,因为格子越少,赚得越少,下面的一定赚不了  
            break;  
        }  
        //最终有收获,该买  
        int numOfBuy = (remain[p] < money / Q[x]) ? remain[p] : money / Q[x];        //能买到的种子的个数  
        remain[p] -= numOfBuy;      //剩余空地减少  
        money -= Q[x] * numOfBuy;       //用去了一部分钱  
        harvestGrid[now+N[x]] += numOfBuy * p;      //更新那些可以收获的日子  
        blank[now+N[x]] += numOfBuy;        //那天会新空出numOfBuy的空地,是值得种植并且能够种植的(赚的钱比原来的成本更多了)(在时间允许下)  
        if(!remain[p]) p--;  
        else break;     //没钱了  
    }  
    return money;  
}  
  
long long cal(int x){  
    memset(harvestGrid, 0, sizeof(harvestGrid));        //初始时没种种子,哪一天都没有收获  
    memcpy(remain, num, sizeof(num));       //初始时所有空地都没种种了,故remain == num  
    memset(blank, 0, sizeof(blank));        //初始化  
    p = 9;  
    now = 0;  
    long long money = work(x, Y);        //第一次购买完种子后剩下的钱  
    for(now = 1; now <= D; now++){      //模拟D天的收获  
        if(!harvestGrid[now]) continue;  
        money += harvestGrid[now] * P[x];      //可以收获的话  
        if(!M[x] && D - now >= N[x]){       //在时间足够的前提下,将刚刚收获的土地继续种植  
            money -= Q[x] * blank[now];       //用去了一部分钱  
            harvestGrid[now+N[x]] += harvestGrid[now];      //更新那些可以收获的日子  
            blank[now+N[x]] += blank[now];        //那天会新空出的空地,是值得种植并且能够种植的(赚的钱比原来的成本更多了)(在时间允许下)  
        }  
        else if(M[x] && D - now >= M[x]){        //在时间足够的前提下,将刚刚收获的土地继续收获  
            harvestGrid[now+M[x]] += harvestGrid[now];      //更新那些可以收获的日子  
        }  
        money = work(x, money);  
    }  
    return money;  
}  
  
void solve(){  
    long long Max = -1;  
    for(int i = 1; i <= A; i++) Max = max(Max, cal(i));  
    printf("%I64d\n", Max);  
}  
  
int main()  
{  
    int T;  
    scanf("%d", &T);  
    while(T--){  
        read();  
        init();  
        solve();  
    }  
    return 0;  
}  

 

 
 
补充:软件开发 , C++ ,
CopyRight © 2022 站长资源库 编程知识问答 zzzyk.com All Rights Reserved
部分文章来自网络,