C语言初试(一)

  不知道这里有没有玩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);

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值