ACM/ICPC 2018亚洲区预选赛北京赛站网络赛 K-Dimensional Foil II(二分瞎搞)

版权声明:转载的时候注明来源就好啦(○’ω’○) https://blog.csdn.net/Murphyc/article/details/82817989

 

传送门

这题其实没有题面看起来复杂,实际上我们贪心的去想:对于下式

                                                                          S=\sum\limits_{i=1}^Na_i^2

如果我们有这么一种操作可以把某个a_i减一,现在问一次操作后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");
        }
    }
}

 

展开阅读全文

没有更多推荐了,返回首页