题目大意

在半径为的圆内放个人,使得相互之间距离尽可能远,即使得尽可能大,表示第i个人与第j个人的欧几里得距离。

解题思路

这道题我们考虑用dp来做。很容易得出,我们的n个点的距离和为:


将其化为加法,可以推出这样的式子:


每次直接求出前面一项,而后面用勾股定理求即可。

AC代码

#include<bits/stdc++.h>
using namespace std;
int dp[10][610][610],ans[40][40];
vector<pair<int,pair<int,int> > > v;
int main()
{
    int t,n,m,s=0,i,j,k,l;
    for(i=-32;i<=32;i++)
        for(j=-32;j<=32;j++)
            v.push_back((make_pair)(i*i+j*j,make_pair(i,j)));
    for(i=0;i<9;i++)
        for(j=0;j<600;j++)
            for(k=0;k<600;k++)
                dp[i][j][k]=-2e9;
    dp[0][300][300]=0;
    sort(v.begin(),v.end());
    for(i=1;i<=30;i++) 
    {
        while(v[s].first<=i*i)
        {
            for(j=1;j<=8;j++)
                for(k=300-i*j;k<=300+i*j;k++)
                    for(l=300-i*j;l<=300+i*j;l++)
                        dp[j][k][l]=max(dp[j][k][l],dp[j-1][k-v[s].second.first][l-v[s].second.second]+v[s].first);
            s++;
        }
        for(j=1;j<=8;j++)
            for(k=0;k<600;k++)
                for(l=0;l<600;l++)
                    if(dp[j][k][l]>0)
                         ans[j][i]=max(ans[j][i],j*dp[j][k][l]-((k-300)*(k-300)+(l-300)*(l-300)));
    }
    scanf("%d",&t);
    while(t--) scanf("%d%d",&n,&m),printf("%d\n",ans[n][m]);
    return 0;
}