题意:
水晶数g,农民数目p,每个农民的造价c,起始状态金钱数m,游戏结束的秒数d。
每秒每个农民可以制造g个水晶。制造农民不需要时间,任何时刻都行。
思路:
刚开始以为是dp。其实不然。
每一秒内都有固定的p[i]、m[i]。i=0,1,2,3......d;
任何时刻都可以生产农民。
讨论对于第i秒内,可以生产农民数目为:x=0,1,2,3.....xmax.;(xmax=m[i-1]/c);
显然是在第i秒初生产最好,这样再第i秒末就可以多出这一秒这个新农民生产的水晶。
p[i]是第i秒末的人数,即上一秒的人数加上在这一秒初新造出的农民数,即p[i]=p[i-1]+x;
m[i]是第i秒末的钱,m[i]=m[i-1]+(p[i])*g-x*c。
目的是使m[d]得到最大值。写到这里其实就可以进行暴力枚举x的值,这样的时间复杂度为O(x^3);
但是注意到,其实x[i]还有一个约束条件。
假设x[i]取值为k,此时就多出k个农民,这时的代价是k*c,而增益呢?增益其实很好算。
对结果m[d]就是(d-i+1)*k*g。
设y=(d-i+1)*k*g-k*c;
所以如果y>0,即(d-i+1)*g-c>0则这个k值才可取。并且!
此时k值取值唯一:我们要的是y越大越好,即k越大越好,所以取k=m[i-1]/c.
实为好题!
实际代码里p不需要开一个数组,因为每个i的x取值唯一,所以直接每次p=p+x即可。
#include<iostream> using namespace std; const int N=105; int G,P,C,M,D; int m[N]; int main() { while(scanf("%d%d%d%d%d",&G,&P,&C,&M,&D)!=EOF) { memset(m,0,sizeof(m)); m[0]=M; for(int i=1;i<=D;i++) { int x=0; if((D-i+1)*G-C>0) { x=m[i-1]/C; P=P+x; } m[i]=m[i-1]+P*G-x*C; } printf("%d\n",m[D]); } return 0; }