不知道这里有没有玩ikariam的啊,我倒觉得蛮不错的。昨天晚上准备资源、科技要开二村,分配工人的时候却苦了我。
每个空闲人口提供3Gold/hour的金币产量,每个木头工人提供1Building material/hour的木头产量。如果仅仅是这样,那就没什么难处了。关键是一个“满意度”的设定,当时我的城里有~188的满意度(satisfaction),每一点满意度提供0.02/hour的人口增长,人口每多1,满意度下降1。
由于这样的设定,使得判断Gold的数量变得困难。正好在学习C语言,今天突发奇想,决定写一个程序,帮助判断应该安排的工人、科学家人数,以达到经一段时间让所有资源同时准备好的条件。
那就开始动吧,首先是确定数据之间的依赖关系:
satisfy(t)=satisfy(0)+population(t)-population(0);
d population(t)/dt=0.02satisfy(t);
解这个常微分方程,得到 population~t 关系:
population(t)=population(0)+satisfy(0)*(exp(0.02t)-1); /*原来程序是这里搞错了*/
对 t 积分,得到 gold~t 关系:
gold(t)=gold(0)+3(population(0)-satisfy(0))*t+150satisfy(0)*exp(0.02t);
当然,这实在全民皆G(0工人or科学家)的条件下。考虑到工人和科学家:
material(t)=material(0)+matworker*t;
research(t)=research(0)+scientist*t;
luxury(t)=luxury(0)+luxworker*t;
Gold(t)=gold(t)-3matworker*t-3*luxworker*t-9scientist*t; (PS:看来科研是最浪费的……)
然后,就该收网了:
material needed……needmat
luxury needed……needlux
research needed……needres
gold needed……needgold
从而有
needmat=mat(0)+matwork*t;
needres=res(0)+scient*t;
needlux=lux(0)+luxwork*t;
needgold=Gold(t);
由于我的最终目的是让所有资源同时ready,因此,显而易见的,上述4式中,t是同样的,化简:
3(population(0)-satisfy(0))*t+150satisfy(0)*exp(0.02t)
=needgold+3*(needmat-mat(0))+3*(needlux-lux(0))+9*(needres-res(0))-gold(0);
(右边记为A,t系数记为B,exp系数记为C)
A=B*t+C*exp(0.02t);
到这里,答案越来越浮出水面了,程序解此方程,得到 t ,代入
needmat=mat(0)+matwork*t;
needres=res(0)+scient*t;
needlux=lux(0)+luxwork*t;
得到matwork、scient、luxwork。
还没完……人口上限问题还没解决。houses限制了最大population,因此还有下面的分析:
令population(t)=population(0)+satisfy(0)*(exp(0.02t)-1) ==houses;
解得 tfull=50*ln(1+(houses-population(0))/satisfy(0));
应用迭代求得的 t 若是小于 tfull ,自然没有问题,若 t>tfull
needgold==Gold(t)=gold(tfull)+houses*(t-tfull)-3matworker*t-3*luxworker*t-9scientist*t;
needmat=mat(0)+matwork*t;
needres=res(0)+scient*t;
needlux=lux(0)+luxwork*t;
解得:t=
tfull+(needgold-gold(tfull))+3*(needmat-mat(0))+3*(needlux-lux(0))+9*(needres-res(0)))/houses
这就是超出 tfull 时的 t 的处理了。
数学问题解决了,就该程序了,
结果算法出了大问题…………
眼看今天也要结束了,也有点累了,就来这里写点东西,权当检查算法,(而且目的也达到了),等明天接着做。
上传个.c 都这么难……选择性的贴几段吧:
输入:
void input(int *gold,int *material,int *luxury,int *satisfy,int *pop,int *house,int *research,int *needgold,int *needmat,int *needlux,int *needres)
{
printf("\ngold:");
scanf("%d",gold);
/*……*/
}
输出:
void output(int matwork,int luxwork,int scient,float time)
{
printf("\nI recommand you assigning\n%d material workers,\n",matwork);
printf("\n%d luxury workers,\n",luxwork);
printf("\n%d scientists.\n",scient);
printf("\nIn this way,your goal will be achieved within\n");
ShowTime(time);
printf(".\n");
}
void ShowTime(float time)
{
int d,h,m,s;
h=floor(time);
time-=h;
time*=60;
m=floor(time);
time-=m;
time*=60;
s=floor(time);
d=h/24;
h%=24;
if(d)
{
if(d==1) printf("1 day ");
else printf("%d days ",d);
/*……*/
}
核心:
float gettime(int needgold,int gold,int needmat,int material,int needlux,int luxury,int needres,int research,int pop,int satisfy,int house)
{
float tfull; /* the time needed to fufill all the houses */
int gfull;
float A,B,C,t=1.0,pret=0.0;
A=(needgold-gold)+3*(needmat-material)+3*(needlux-luxury)+9*(needres-research);
B=3*(pop+satisfy);
C=150*satisfy;
while(abs(pret-t)>=1.0/3600)
{
pret=t;
t=(C*exp(-0.02*pret)-A)/B;
}
printf("%.4f",t);
tfull=gettfull(house,pop,satisfy);
if(t<=tfull) return t;
gfull=getgfull(pop,satisfy,gold,tfull);
printf("%d\n",gfull);
t=tfull+((needgold-gfull)+3*(needmat-material)+3*(needlux-luxury)+9*(needres-research))/house;
return t;
}
main函数:
main()
{
/*…………*/
input(&gold,&material,&luxury,&satisfy,&pop,&house,&research,&needgold,&needmat,&needlux,&needres);
time=gettime(needgold,gold,needmat,material,needlux,luxury,needres,research,pop,satisfy,house);
matwork=((needmat-material)/time+0.5);
luxwork=((needlux-luxury)/time+0.5);
scient=((needres-research)/time+0.5);
output(matwork,luxwork,scient,time);
}