题目大意
在半径为的圆内放个人,使得相互之间距离尽可能远,即使得尽可能大,表示第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; }