Garland
(garland.pas/cpp/in/out)
时间限制: 2.0 second
内存限制: 16 MB
问题描述
有这个图
并且满足:
H1 = A
Hi = (H[i−1] + H[i+1])/2 − 1, 1 < i < N
HN = B
Hi ≥ 0, for all1 ≤ i ≤ N
求给定最左边的A点和个数N,求最右边B点的最低值。
输入格式:两个数,分别表示N,A
整数N (3 ≤ N ≤ 1000),实数A (10 ≤ A ≤ 1000)
Sample input
692 532.81
Sample Output
446113.34
这是一道O(1)的数学题,我用的O(n)的算法,OJ说他是一道O(nlgn)的题。
可以推出通项公式来。关于h1和h2的。
然后容易想到的是必然最多有一个凸,即一个下凸,而且,我们这个凸的最下端我们可以将它移动到x轴上而更优。
于是考虑没有凸的情况。B点是最低点,我们必然也可以将它移动到x轴上而更优。
因此,得出结论,必然有且仅有一个零点。
枚举这一个零点,用通项公式,根据hi=0,h1=a算出h2来,然后就可以求hn了。
另外必须保证h2,hi-1和hi+1都是大于等于0的。
我只过了六十多分。。悲剧。。不太清楚为什么,这几组错了的答案全是0,而我输出的是+oo,不太清楚原因呀。
#include <cstdio>
#include <string>
#define MIN(a,b) ((a)<(b)?(a):(b))
long getint()
{
long rs=0;char tmp;bool sgn=1;
do tmp = getchar();
while (!isdigit(tmp)&&tmp-'-');
if (tmp == '-'){sgn=0;tmp=getchar();}
do rs = (rs<<1)+(rs<<3)+tmp-'0';
while (isdigit(tmp=getchar()));
return sgn?rs:-rs;
}
int main()
{
freopen("garland.in","r",stdin);
freopen("garland.out","w",stdout);
long n = getint();
double h1;
scanf("%lf",&h1);
double h2,hip1,hn,hid1;
double ans = 1e19;
for (long i=3;i<n+1;i++)
{
h2 = (double(i-2)/double(i-1))*h1-(i-2);
if (i == 3) hid1 = h2;
else {hid1 = (i-2)*(h2)-(i-3)*(h1)+(i-2)*(i-3);}
if (hid1 < 0) continue;
hip1 = 2-hid1;
if (hip1 < 0) continue;
hn = (n-i)*hip1+(n-i)*(n-i-1);
if (hn < 0) continue;
ans = MIN(ans,hn);
}
if (ans < 1e19)
printf("%.2lf",ans);
else
printf("0.00");
return 0;
}