暴力枚举 三分
我们考虑山的高度范围为 [ 0 , 100 ] [0, 100] [0,100], 因此, 我们一定能找到一个 l ∈ [ 0 , 83 ] , r = l + 17 l in [0, 83], r = l + 17 l∈[0,83],r=l+17, 使得所有山峰高度位于 [ l , r ] [l, r] [l,r]区间时, 花费最小.
因此思路1: 我们可以暴力枚举所有左端点, 然后所有花费取最小值即可
考虑优化思路1, 因为通常题目的值域范围不会那么小, 如果值域变为 [ 0 , 1 0 9 ] [0, 10^9] [0,109], 我们如何去做呢?
我们发现, 如果以左端点 l l l的选取建立 O x Ox Ox, 以花费 c o s t cost cost建立 O y Oy Oy, 那么整体函数图像应该是呈现一个开口向上的二次函数形式. 我们可以通过三分来求解.
因此思路2: 三分区间左端点.
我通常习惯用浮点数三分的方式, 来处理整数三分, 最后判断的时候, 判断一下三分结果左右的一个小区间即可.
在进行最后的小区间判断时, 由于我们之前的判断函数返回的是浮点数类型, 而答案是整型. 如果怕有精度问题, 可以重写一个计算函数.
#include <bits/stdc++.h>
#define rep(i, n) for (int i = 1; i <= (n); ++i)
using namespace std;
typedef long long ll;
const int N = 1E3 + 10;
int a[N];
int main()
{int n; cin >> n;rep(i, n) scanf("%d", &a[i]);int res = INT_MAX;for (int h = 0; h <= 83; ++h) {int now = 0;rep(i, n) {if (a[i] >= h and a[i] <= h + 17) continue;int up = h + 17;now += min((a[i] - h) * (a[i] - h), (a[i] - up) * (a[i] - up));}res = min(res, now);}cout << res << endl;return 0;
}
#include <bits/stdc++.h>
#define rep(i, n) for (int i = 1; i <= (n); ++i)
using namespace std;
typedef long long ll;
const int N = 1E3 + 10;
const double eps = 1E-6;
int n;
int a[N];
double fact(double x) {double res = 0;double up = x + 17;rep(i, n) {if (a[i] >= x and a[i] <= up) continue;double qaq = min((a[i] - x) * (a[i] - x), (a[i] - up) * (a[i] - up));res += qaq;}return res;
}
int main()
{cin >> n;rep(i, n) scanf("%d", &a[i]);double l = 0, r = 83;while (r - l > eps) {double mid = (l + r) / 2;double midl = mid - eps, midr = mid + eps;if (fact(midl) < fact(midr)) r = midl;else l = midr;}int res = INT_MAX;for (int i = max<int>(l - 5, 0); i <= l + 5; ++i) {res = min<int>(res, fact(i)); //如果怕有精度问题, 可以再写一个函数计算}cout << res << endl;return 0;
}
本文发布于:2024-01-28 18:34:35,感谢您对本站的认可!
本文链接:https://www.4u4v.net/it/17064380799427.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
留言与评论(共有 0 条评论) |