HihoCoder 1835 K-Dimensional Foil II ICPC2018 北京网络赛

http://www.cnblogs.com/DevilInChina/p/9691126.html

这个dalao 的思路

设平移球心到原点后 当前飞船坐标为 p(y_1,y_2,..,y_k) 球面上该点坐标q(a_1,a_2,...,a_k)

设 F(p) = sigma(yi-ai)^2 +lam*(sigema(ai) -R)

对每个ai求偏导后加起来可以得到lam ai yi 的关系式

根据关系式不断逼近最值即可

#include <bits/stdc++.h>
using namespace std;
#define LL long long
const int maxn=1e2+10;
int c[maxn];
int y[maxn];
int f[maxn];
double a[maxn];
double b[maxn];
int n,k,r;
int sgn(int x)
{
    return x>=0? 1:-1;
}
#define eps 1e-6
bool check()
{
    for(int i=0;i<k;i++)
    {
        if(fabs(a[i]-b[i])>eps)return false;
    }
    return true;
}

void deal()
{
    static int finish[maxn];
    for(int i=0;i<k;i++)
        finish[i]=0;
    double lam=0;
    bool flag;
    do{
        //lam=(sigma y[i] -r)/n
        //a[i]=y[i]-lam
        lam=0;
        int tot=0;
        for(int i=0;i<k;i++)
            if(!finish[i]) lam+=y[i],tot++;
        lam=(lam-r)/tot;
        flag=false;
        for(int i=0;i<k;i++)
        {
            if(finish[i])continue;
            a[i]=-lam+y[i];
            if(a[i]<=0)a[i]=0,finish[i]=1,flag=true;
        }
    }while(flag);
}
void deal2() //第二种方法 不断的给这个向量各个维度等大的截断,某维度没有那么长就置0,直到这个向量的"长度"为R(这里是题目要求的欧氏距离)
{
    static int ok[maxn];
    for(int i=0;i<k;i++)
        ok[i]=0;
    double sum=accumulate(y,y+k,(double)-r); //加和过程中会把元素类型转换为init类型
    bool flag=true;
    int tot=k;
    while(flag)
    {
        flag=false;
        double avg=sum/tot;
        for(int i=0;i<k;i++)
            printf("%.4f ",a[i]);printf("%f\n",avg);
        for(int i=0;i<k;i++)
        {
            if(ok[i])continue;
            a[i]=y[i]-avg;
            if(a[i]<=0)
            {
                ok[i]=1;
                a[i]=0;
                sum-=y[i];
                tot--;
                flag=true;
                break;
            }
        }

    }
}
int main()
{
    #ifdef shuaishuai
    freopen("in.txt","r",stdin);
    #endif // shuaishuai
    int t;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d%d%d",&n,&k,&r);
        for(int i=0;i<k;i++)
            scanf("%d",c+i);
        while(n--)
        {
            for(int i=0;i<k;i++)
            {
                scanf("%d",y+i);
                f[i]=sgn(y[i]-c[i]);
                y[i]=abs(y[i]-c[i]);
            }
            deal2();
            for(int i=0;i<k;i++)
                printf("%.4f%c",a[i]*f[i]+c[i],i==k-1?'\n':' ');
        }
    }
    return 0;
}

 

posted @ 2018-10-16 00:30  BIack_Cat  阅读(211)  评论(0编辑  收藏  举报