【NOI2000T1】瓷片项链-二次函数的最值

测试地址:瓷片项链

注意,该测试地址中的式子写错了,应该是D=0.3*(V-V0)^0.5(也就是D=0.3*sqrt(V-V0)),漏了一个^0.5,看得我不明所以...找到了原题才知道少了个根号。

做法:设分成s块,要求总长W=sD最大,化一下式子:

W=sD=s*0.3*sqrt(V总/s-V0)=0.3*sqrt(V总s-V0s^2)

注意到根号内的式子(V总s-V0s^2)是一个关于s的二次函数,这个式子越大,W就越大,所以问题转化为求二次函数(V总s-V0s^2)取最大值时s的取值,由于二次项系数小于0,所以函数在顶点处取最大值,由初中的数学知识得bests=V总/(2*V0)。然而,bests可能不是整数,而问题要求整数解,由二次函数的图象可知,离顶点横坐标越接近的点的函数值越大,所以我们就比较bests与其向下和向上取整的整数之间的差的绝对值,与哪个的差值小就选哪个作为真正的bests,如果差值相等,说明有两个整数最优解,按照题目要求输出0。还要注意一点,如果在s=bests时函数值为负数,这种情况是无解的,因为原式没有意义。

所以总归来说这题还是很水的......完全是初中知识嘛,写起代码来也是只有20多行,多年前的NOI果然水啊。

以下是本人代码:

#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#include <cmath>
#define e 1e-7
using namespace std;
double vt,v0,best,c,ans;

int main()
{
  scanf("%lf%lf",&vt,&v0);
  
  best=vt/(2*v0);
  c=(int)best+0.5;
  if (fabs(best-c)<e) {printf("0");return 0;}
  else if (best<c) best=(int)best;
       else best=(int)best+1;
  
  ans=0.3*best*sqrt(vt/best-v0);
  if (ans<0) printf("0");
  else printf("%.0lf",best);
  
  return 0;
}


posted @ 2017-03-09 11:25  Maxwei_wzj  阅读(154)  评论(0编辑  收藏  举报