模拟,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;
}