- 链接:http://acm.hdu.edu.cn/showproblem.php?pid=4355
- 题意:给定一些点的位置和他们的权重,计算一个目的地,使得所有点到这个目的地的函数值之和最小。函数值为 距离之差的立方 * w。
- 分析: 此题应该是裸的三分搜索的模板题,因为题中说明,每个点的位置是按照 x[i] <= x[i+1] 输入的,所以三分搜索的边界 l = x[0], r = x[N-1]。因为是小数点后一位的位置,所以EPS 精确到 1e-4即可。
Notes: 如果三分搜索不懂的话,看此文章
https://blog.csdn.net/qq_39763472/article/details/105061044
- 代码:
#include "bits/stdc++.h"
using namespace std;
#define mem(a,b) memset(a,b,sizeof(a))
#define pb push_back
#define mk make_pair
typedef long long ll;
const int maxn = 1e5 + 7;
const int INF = 0x3f3f3f;
const double EPS = 1e-4;
int t,N;
struct Point{
double weigh,pos;
Point(double w,double p):weigh(w),pos(p){};
};
vector<Point> vp;
double com(double pos){
double ans = 0.0;
for (int i = 0; i < N; i++) {
double dis = fabs(vp[i].pos - pos);
double w = vp[i].weigh;
ans += pow(dis,3)*w;
}
return ans;
}
int main(){
// freopen("1.txt","r",stdin);
ios::sync_with_stdio(0);
cin.tie(0);
scanf("%d",&t);
for (int kase = 1; kase <= t; kase++) {
scanf("%d",&N);
vp.clear();
double w,p;
for (int i = 0; i < N; i++) {
scanf("%lf%lf",&p,&w);
vp.pb(Point(w,p));
}
double l = vp[0].pos, r = vp[N-1].pos;
while (r - l > EPS) {
double midl = l + (r - l)/3;
double midr = r - (r - l)/3;
if (com(midl) > com(midr)) {
l = midl;
}else r = midr;
}
int ans = floor(com(l) + 0.5);
cout<<"Case #"<<kase<<": "<<ans<<endl;
}
return 0;
}
- 遇到的问题:
(1)cin会wa。虽然用cin.tie(0) 以及 sync_with_stdio(0)取消了cin和stdin的同步,但是这样会使得cin的速度接近于scanf,在数据较大时,还是需要使用scanf 和printf!
(2)关于 四舍五入, 英文是 nearest integer,最近的整数。用刘汝佳大神告知我们的 floor取整函数, 即 floor(ans + 0.5) 来做到四舍五入。