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
这是一道数学题
突破口在于Hi = (H[i−1] + H[i+1])/2 − 1, 1 < i < N 通过变形可以得到H[i + 1] = 2 * H[i] + 2 - H[i - 1]通过数列的操作或者是吴一昊的菜B迭代法可以得出以下公式
H[k + 1] = H[1] + k * (H[2] - H[1]) + k * (k - 1)
于是H[n] = (n - 1)(H[2] - H[1]) + H[1] + (n - 1) * (n - 2)
令R = (H[2] - H[1])
由于H[k + 1] = H[1] + k * (H[2] - H[1]) + k * (k - 1) >= 0
即H[1] + k * R + k * (k - 1) >= 0即R >= -k + 2 - H[1] / (k - 1)
令k = k + 1
则R >= -(H1 / k + k) + 1
因为k == sqrt(H1)时 R 最小
此时H[n]最小(H[n] = (n - 1)R + H[1] + (n - 1) * (n - 2))
然后考虑精度这里略过
重点是一个类似松弛操作的做法
若存在一条曲线使得B点是0点 且左方存在点在X轴下 那就可以通过使最低点向上移动 左方的点就会上移 也就是说
不存在无解的情况
也就是说 H[B]min == 0
所以若k > N输出0(不必特殊处理)
代码如下
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <iomanip>
#define min(a, b) (a < b ? a : b)
namespace Solve
{
int N;
double ans;
double h1;
double k;
double Z;
double R = 100000000;
void Init_file();
void Read_data();
void Work();
void solve();
}
void Solve::Init_file()
{
freopen("garland.in", "r", stdin);
freopen("garland.out", "w", stdout);
}
void Solve::Read_data()
{
scanf("%d%lf", &N, &h1);
}
void Solve::Work()
{
ans = (N - 1) * (N - 2);
k = ceil(sqrt(h1));
if(k < N) R = h1 / k + k;
k = floor(sqrt(h1));
if(k < N) R = min(R, h1 / k + k);
if(R == 100000000) R = h1 / (N - 1) + N - 1;
R = -R;
Z = R + 1;
ans += Z * (N - 1) + h1;
printf("%.2lf", ans);
}
void Solve::solve()
{
Init_file();
Read_data();
Work();
}
int main()
{
Solve::solve();
return 0;
}