枚举间距会发现,如果间距过大或过小都会让答案太大。所以可以得出答案关于点间距的函数应该是个凹函数。
一开始怎么跑都超时, 后来强制跑了300次WA23 700次就过了。
××这次学会了强制让二分和三分缩小查找次数。
××范围 和强制对的次数都比较重要。
#include<bits/stdc++.h> #define inf 0x3f3f3f3f using namespace std; const int N=505; const double eps = 1e-15; double p[N]; int n; int chan; double mbs(double a){ return a>=0?a:-a; } double check(double X){ double ans = inf; for(int i=1;i<=n;i++){ double tpans = 0; for(int j=1;j<i;j++){ tpans += mbs(p[i] - (i - j)*X - p[j]); } for(int j=i+1;j<=n;j++){ tpans += mbs(p[i] + (j - i)*X - p[j] ) ; } if(tpans < ans){ ans = tpans; chan = i; } } return ans; } int main() { // freopen("input.txt", "r", stdin); // freopen("output.txt","w", stdout); scanf("%d", &n); for(int i=1;i<=n;i++){ scanf("%lf",&p[i]); } double l = 0, r = 1000000.0; int cnt = 700; while(eps<mbs(r - l) && cnt--){ double mid = (l+r)/2; double midd = (mid + r)/2; if(check(mid) > check(midd)+eps){ l = mid; } else r = midd; } l = check(l)>check(r)?r:l; double ans = check(l); printf("%.4f\n", ans); for(int i=1;i<chan;i++){ printf("%.10f ", p[chan] -(chan-i)*l); } printf("%.10f ", p[chan]); for(int i=chan+1;i<=n;i++){ printf("%.10f ",p[chan]+(i-chan)*l); } return 0; }