- 鏈接: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) 來做到四捨五入。