2020牛客暑期多校训练营(第七场) Social Distancing

原题
题目描述
在这里插入图片描述
样例
输入

4 4 6
2 1 2
0
2 2 3
1 4
4 2
2 3
2 1
2 2
4 2
4 1

输出

2
3
-1
3
4
3

思路
因为这道题的范围比较小,所以可以直接暴力打表,这样也可以 A C AC
不过,这道题可以用动态规划来做,这样可以减少时间复杂度。
脑袋一拍,我们会知道,要尽把点都放在圆上,而且两个点的间隔要尽量地大。
这样就可以列出 n n 个点的距离和为
在这里插入图片描述
s i g m a sigma d p dp 转移式都比较烦,而且还有减法,所以我们可以化简一下,并把减法转换为加法
在这里插入图片描述
这样就可以很舒服地做 d p dp 了,具体细节可以参考以下的代码。
代码

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

猜你喜欢

转载自blog.csdn.net/bbbll123/article/details/107786187