BOJ1923 Hector的面试 I 贪心

题意:

水晶数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;
}


你可能感兴趣的:(BOJ1923 Hector的面试 I 贪心)