ACM/ICPC 2018亞洲區預選賽北京賽站網路賽 K-Dimensional Foil II(二分瞎搞)
阿新 • • 發佈:2019-02-14
這題其實沒有題面看起來複雜,實際上我們貪心的去想:對於下式
如果我們有這麼一種操作可以把某個減一,現在問一次操作後S的最小值,
那麼很容易便可以知道我們肯定是去找最大的那個去減一,最後的結果才會最小.
對於這道題其實也一樣,我們肯定也是選相對於圓心數值的差(加絕對值)大的維度優先去減小,這樣一直貪心下去,
最後落到上面的點肯定就是我們要求的點。
對於這樣一種操作,我們可以發現,在經過若干次操作後,這k個維度的向量的長度的最大的那幾個肯定數值是相等的,
這是由於我們貪心的選取最大的去減所導致的,由於我們每次減的數值很小,誤差小於題目中給的1e-4,那麼對於結果來說數值就是無誤的.
這樣一來,對於這麼些操作我們便可以用二分去替代,二分我們最後劃定的那個最大值的數值便可以解決此問題。
#include<bits/stdc++.h> using namespace std; double eps=1e-6; double c[105],s[105]; double conv[105]; double ans[105]; int main() { int t; scanf("%d",&t); while(t--) { int n,k,r; scanf("%d%d",&n,&k); scanf("%d",&r); for(int i=1;i<=k;i++) scanf("%lf",&c[i]); for(int i=1;i<=n;i++) { for(int j=1;j<=k;j++) scanf("%lf",&s[j]),conv[j]=abs(s[j]-c[j]); double L=0,R=1e8; while(L<R-eps) { double mid=(L+R)/2.0; double sum=0; for(int j=1;j<=k;j++) sum+=max(0.0,conv[j]-mid); if(sum<=r) R=mid; else L=mid; } for(int j=1;j<=k;j++) { if(conv[j]>=R) conv[j]=R; if(s[j]>c[j]) ans[j]=-conv[j]+s[j]; else ans[j]=conv[j]+s[j]; printf("%.5f ",ans[j]); } printf("\n"); } } }