您的位置:首页 > 其它

2020暑期牛客多校训练营第七场(A)Social Distancing(平面几何,动态规划,打表)

2020-08-02 22:40 627 查看

Social Distancing

原题请看这里

题目描述:

如今,梦网王国正遭受着全国性的流行病。 幸运的是,宝宝社长正在与疾病控制中心(CDC)(CDC)(CDC)进行有效合作,他们正在尽最大努力使一切都受到控制。宝宝社长宣布了一项社会隔离政策,以防止病毒传播。 作为CDCCDCCDC的负责人,您需要研究以下问题:
有n个人需要观察,并且您已经在222维平面上的(0,0)(0,0)(0,0)中设置了监视器。 每个人都应保持在r到显示器的距离之内。 您还必须使它们尽可能远离彼此。 为了简化问题,您只能将它们分配给整数坐标。
请最大化∑i=1n−1∑j=i+1nd(i,j)2\sum_ {i=1}^{n-1}\sum_{j = i + 1} ^ {n} d(i,j)^2∑i=1n−1​∑j=i+1n​d(i,j)2,
其中d(i,j)d(i,j)d(i,j)表示第iii个人与第jjj个人之间的欧几里得距离。

输入描述:

有多个测试用例。 输入的第一行包含一个整数T(1≤T≤250)T(1 \leq T \leq 250)T(1≤T≤250),表示测试用例的数量。
对于每个测试用例,唯一的行包含两个整数n,r(1≤n≤8,1≤r≤30)n,r(1 \leq n \leq 8,1 \leq r \leq 30)n,r(1≤n≤8,1≤r≤30)。

输出描述:

对于每个测试用例,请在一行中输出答案。

样例输入:

2
4 2
5 10

样例输出:

64
2496

思路:

动态规划。
首先我们可以想到n个点的距离和为:
∑i=1n∑j=1n(xi−xj)2(yi−yj)2\sum^n_{i=1}\sum^n_{j=1}(x_i-x_j)^2(y_i-y_j)^2∑i=1n​∑j=1n​(xi​−xj​)2(yi​−yj​)2
由于这个式子中有减法,较难维护,所以我们考虑把他转化成加法的形式:
∑i=1n∑j=1n(xi−xj)2(yi−yj)2=n∗∑i=1nx2+y2−(∑i=1xnxi2+yi2)2\sum^n_{i=1}\sum^n_{j=1}(x_i-x_j)^2(y_i-y_j)^2=n*\sum^n_{i=1}x^2+y^2-(\sum^n_{i=1x}x_i^2+y_i^2)^2∑i=1n​∑j=1n​(xi​−xj​)2(yi​−yj​)2=n∗∑i=1n​x2+y2−(∑i=1xn​xi2​+yi2​)2
前一项可以直接得到,后一项可以通过勾股定理求得,然后就可以dpdpdp了
由于数据范围较小,也可以算出所有答案后打表查询来做。

ACACAC CodeCodeCode 1:

(dpdpdp预处理+O(1)O(1)O(1)查询)

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int MAXN=300;
const int mx=32;
int dp[9][MAXN*2][MAXN*2],ans[MAXN][MAXN];
vector<pair<int,pair<int,int> > > vec;
void ycl()
{
int s=0;
for(int i=-mx;i<=mx;++i)
for(int j=-mx;j<=mx;++j)
vec.push_back(make_pair(i*i+j*j,make_pair(i,j)));
sort(vec.begin(),vec.end());
memset(dp,-0x3f*2,sizeof(dp));
dp[0][MAXN][MAXN]=0;
for(int r=1;r<=30;++r){
while(vec[s].first<=r*r){
for(int i=1;i<=8;++i)
for(int j=MAXN-r*i;j<=MAXN+r*i;++j)
for(int k=MAXN-r*i;k<=MAXN+r*i;++k)
dp[i][j][k]=max(dp[i][j][k],dp[i-1][j-vec[s].second.first][k-vec[s].second.second]+vec[s].first);
s++;
}
for(int n=1;n<=8;++n)
for(int h=0;h<2*MAXN;++h)
for(int l=0;l<2*MAXN;++l)
if(dp[n][h][l]>0)
ans[n][r]=max(ans[n][r],n*dp[n][h][l]-((h-MAXN)*(h-MAXN)+(l-MAXN)*(l-MAXN)));
}
}
int t,n,r;
int main(){
ycl();
scanf("%d",&t);
while(t--){
scanf("%d%d",&n,&r);
printf("%d\n",ans[n][r]);
}
}

ACACAC CodeCodeCode 2:

打表,总时间复杂度O(1)O(1)O(1)。

#include<bits/stdc++.h>
#define ll long long
using namespace std;
int ans[50][50]={{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},{0,4,16,36,64,100,144,196,256,324,400,484,576,676,784,900,1024,1156,1296,1444,1600,1764,1936,2116,2304,2500,2704,2916,3136,3364,3600},{0,8,32,76,130,224,312,416,554,722,896,1064,1248,1512,1746,2016,2264,2600,2888,3218,3584,3912,4344,4712,5138,5612,6062,6536,6984,7520,8084},{0,16,64,144,256,400,576,784,1024,1296,1600,1936,2304,2704,3136,3600,4096,4624,5184,5776,6400,7056,7744,8464,9216,10000,10816,11664,12544,13456,14400},{0,24,96,218,384,624,880,1188,1572,2014,2496,2984,3520,4224,4870,5616,6336,7224,8056,9008,9984,10942,12080,13144,14326,15624,16896,18184,19488,20968,22480},{0,36,144,324,576,900,1296,1764,2304,2916,3600,4356,5184,6084,7056,8100,9216,10404,11664,12996,14400,15876,17424,19044,20736,22500,24336,26244,28224,30276,32400},{0,48,192,432,768,1224,1740,2356,3102,3954,4896,5872,6960,8280,9564,11016,12456,14160,15816,17666,19584,21500,23688,25808,28122,30624,33120,35664,38266,41200,44076},{0,64,256,576,1024,1600,2304,3136,4096,5184,6400,7744,9216,10816,12544,14400,16384,18496,20736,23104,25600,28224,30976,33856,36864,40000,43264,46656,50176,53824,57600}};
int main()
{
int t;
scanf("%d",&t);
while(t--){
int n,r;
scanf("%d%d",&n,&r);
printf("%d\n",ans[n][r]);
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: