这题其实没有题面看起来复杂,实际上我们贪心的去想:对于下式
如果我们有这么一种操作可以把某个减一,现在问一次操作后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");
}
}
}