题意:
二维平面上你要确定n个点的位置,使得他们到零点的距离不超过r,且
要最大
题解:
有模拟退火的做法,,没看过,也不是很懂怎么样才能多源点往最优方向走。
这个式子转换一下:
→
∑
i
=
1
n
−
1
∑
j
=
i
+
1
n
(
x
i
−
x
j
)
2
+
(
y
i
−
y
j
)
2
\rightarrow\sum\limits_{i=1}^{n-1}\sum\limits_{j=i+1}^{n}(x_i-x_j)^2+(y_i-y_j)^2
→i=1∑n−1j=i+1∑n(xi−xj)2+(yi−yj)2
→
∑
i
=
1
n
−
1
∑
j
=
i
+
1
n
x
i
2
+
x
j
2
+
y
i
2
+
y
j
2
−
2
x
i
x
j
−
2
y
i
y
j
\rightarrow\sum\limits_{i=1}^{n-1}\sum\limits_{j=i+1}^{n}x_i^2+x_j^2+y_i^2+y_j^2-2x_ix_j-2y_iy_j
→i=1∑n−1j=i+1∑nxi2+xj2+yi2+yj2−2xixj−2yiyj
那么我们需要手模一下这个式子,然后会发现,左边
x
i
2
+
x
j
2
x_i^2+x_j^2
xi2+xj2这里,每个x都会出现n-1次,然后的话,我们这里多加一个
x
i
2
x_i^2
xi2,然后后面
−
2
x
i
x
j
-2x_ix_j
−2xixj这里给他一个
x
i
2
x_i^2
xi2,于是后面就变成了一个多项式展开,然后式子就变成了这样:
→
∑
i
=
1
n
(
x
i
2
+
y
i
2
)
−
(
∑
i
=
1
n
x
i
)
2
−
(
∑
i
=
1
n
y
i
)
2
\rightarrow\sum\limits_{i=1}^{n}(x_i^2+y_i^2)-(\sum\limits_{i=1}^{n}x_i)^2-(\sum\limits_{i=1}^{n}y_i)^2
→i=1∑n(xi2+yi2)−(i=1∑nxi)2−(i=1∑nyi)2
那么我们要维护
∑
i
=
1
n
x
i
\sum\limits_{i=1}^{n}x_i
i=1∑nxi和
∑
i
=
1
n
y
i
\sum\limits_{i=1}^{n}y_i
i=1∑nyi
dp[i][j][k]就表示已经有了i个点的时候,j表示x的累加,k表示y的累加,
∑
i
=
1
n
(
x
i
2
+
y
i
2
)
\sum\limits_{i=1}^{n}(x_i^2+y_i^2)
i=1∑n(xi2+yi2)的累加的答案。
可以打表,如果需要同时枚举x,y会T。
但是这里有一点:x和y要贪心的更大,那么知道了x,y就是r*r-x*x
那么DP非常的暴力
#include<bits/stdc++.h>
using namespace std;
const int N=305,M=10;
int dp[M][N*2][N*2],ans[M][N];
int main()
{
memset(dp,-1,sizeof(dp));
dp[0][N][N]=0;
for(int r=1;r<=30;r++){
for(int x=-r;x<=r;x++){
int y=sqrt(r*r-x*x);
for(int i=1;i<=8;i++)
for(int j=N-r*i;j<=N+r*i;j++)
for(int k=N-r*i;k<=N+r*i;k++){
if(~dp[i-1][j-x][k-y])
dp[i][j][k]=max(dp[i][j][k],dp[i-1][j-x][k-y]+x*x+y*y);
if(~dp[i-1][j-x][k+y])
dp[i][j][k]=max(dp[i][j][k],dp[i-1][j-x][k+y]+x*x+y*y);
}
}
for(int i=1;i<=8;i++)
for(int j=N-r*i;j<=N+r*i;j++)
for(int k=N-r*i;k<=N+r*i;k++)
if(~dp[i][j][k])
ans[i][r]=max(ans[i][r],dp[i][j][k]*i-(j-N)*(j-N)-(k-N)*(k-N));
}
int t;
scanf("%d",&t);
while(t--){
int x,y;
scanf("%d%d",&x,&y);
printf("%d\n",ans[x][y]);
}
return 0;
}