A-Social Distancing 模拟退火 2020牛客暑期多校训练营(第七场)

https://ac.nowcoder.com/acm/contest/5672/A

可以很简单的理解如果n%2==0,答案就是n*n*r*r,因为由(n-1)多拿一个点时放在最左边和最右边恰好少1,补齐这个1就直接多赚,通过r较小时候的暴力搜索也可以发现这一规律,然而当左边右边恰好相等,再由n-1转移到n时,就不太行

从知乎网友那里学习了一下tot个点中选n个数的这个选择子集合的模拟退火写法,他的代码只考虑了x=-r,r上的边界点,没有考虑y=-r,r时极值边界点,所以他还结合了他队友遗传算法的答案

我稍微调了下参数,比如在t<=4的时候重复10遍探索,然而f[7][27]在1e6次模拟退火时过了,f[7][29]总是找不到,可能还要进一步开大。

经验就是以后打表可以暴力打小部分的,然后最后一个再暴力增大参数,这样才能打出来

#include<bits/stdc++.h>
#define pb push_back
using namespace std;
typedef long long ll;
mt19937 rnd(time(0));
uniform_int_distribution<> dis(1,100000);
const int maxl=3e5+10;
 
int n,r,m,cas,k,l,cnt,tot,ans;
int b[maxl],c[maxl];
int f[50][50];
struct node
{
    int x,y;
    bool operator < (const node &b)const
	{
		if(x==b.x)
			return y<b.y;
		return x<b.x;
	}
	bool operator == (const node &b)const
	{
		return x==b.x && y==b.y;
	}
}a[maxl];
 
inline int dist(const node &a,const node &b)
{
    return (a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y);
}
 
inline void prework()
{
    scanf("%d%d",&n,&r);
    tot=0;
    int y=r;
    for(int x=-r;x<=r;x++)
    {
    	a[++tot]=node{x,(int)sqrt(r*r-x*x)};
		a[++tot]=node{x,-(int)sqrt(r*r-x*x)};
	}
	for(int y=-r;y<=r;y++)
	{
		a[++tot]=node{(int)sqrt(r*r-y*y),y};
		a[++tot]=node{-(int)sqrt(r*r-y*y),y};
	}
	sort(a+1,a+1+tot);
	tot=unique(a+1,a+1+tot)-a-1;
}
 
inline int calc(int b[])
{
    int ret=0;
    for(int i=1;i<n;i++)
        for(int j=i+1;j<=n;j++)
            ret+=dist(a[b[i]],a[b[j]]);
    return ret;
}

inline void anneal()
{
	for(int i=1;i<=n;i++)
		b[i]=dis(rnd)%tot+1;
	int now=calc(b),tmp;
	ans=max(now,ans);
	int t=tot;bool flag;
	while(t)
	{
		flag=true;int cnt=0;
		while(flag || (t<=4 && cnt<=10))
		{
			flag=false;++cnt;
			for(int i=1;i<=n;i++)
				c[i]=b[i];
			for(int i=1;i<=n;i++)
			{
				c[i]=(b[i]+t)%tot+1;
				tmp=calc(c);
				if(now<tmp)
				{
					now=tmp;flag=true;ans=max(ans,now);
					for(int j=1;j<=n;j++)
						b[j]=c[j];
				}
				else if(exp(-(now-tmp))/t>1.0*dis(rnd)/100000)
				{
					now=tmp;
					for(int j=1;j<=n;j++)
						b[j]=c[j];
				}
				c[i]=(b[i]-t+tot)%tot+1;
				tmp=calc(c);
				if(now<tmp)
				{
					now=tmp;flag=true;ans=max(ans,now);
					for(int j=1;j<=n;j++)
						b[j]=c[j];
				}
				else if(exp(-(now-tmp))/t>1.0*dis(rnd)/100000)
				{
					now=tmp;
					for(int j=1;j<=n;j++)
						b[j]=c[j];
				}
			}
		}
		
		t=min((int)(t*0.9),t-1);
	}
}
 
inline void mainwork()
{
    if(n==1)
    {
        ans=0;
        return;
    }
    if(r==1 || n%2==0)
    {
    	ans=0;
		for(int i=1;i<=n;i++)
			ans+=(i/2)*4*r*r;
        return;
    }
    ans=0;
    for(int i=1;i<=100000;i++)//7 27 7 29 需要开到1e6 
    	anneal();
}
 
inline void print()
{
    //printf("%d\n",ans);
    printf("f[%d][%d]=%d;",n,r,ans);
}
 
int main()
{
    //freopen("in.in","r",stdin);
    //freopen("out2.out","w",stdout);
    f[1][1]=0;f[1][2]=0;f[1][3]=0;f[1][4]=0;f[1][5]=0;f[1][6]=0;f[1][7]=0;f[1][8]=0;f[1][9]=0;f[1][10]=0;f[1][11]=0;f[1][12]=0;f[1][13]=0;f[1][14]=0;f[1][15]=0;f[1][16]=0;f[1][17]=0;f[1][18]=0;f[1][19]=0;f[1][20]=0;f[1][21]=0;f[1][22]=0;f[1][23]=0;f[1][24]=0;f[1][25]=0;f[1][26]=0;f[1][27]=0;f[1][28]=0;f[1][29]=0;f[1][30]=0;f[2][1]=4;f[2][2]=16;f[2][3]=36;f[2][4]=64;f[2][5]=100;f[2][6]=144;f[2][7]=196;f[2][8]=256;f[2][9]=324;f[2][10]=400;f[2][11]=484;f[2][12]=576;f[2][13]=676;f[2][14]=784;f[2][15]=900;f[2][16]=1024;f[2][17]=1156;f[2][18]=1296;f[2][19]=1444;f[2][20]=1600;f[2][21]=1764;f[2][22]=1936;f[2][23]=2116;f[2][24]=2304;f[2][25]=2500;f[2][26]=2704;f[2][27]=2916;f[2][28]=3136;f[2][29]=3364;f[2][30]=3600;f[3][1]=8;f[3][2]=32;f[3][3]=76;f[3][4]=130;f[3][5]=224;f[3][6]=312;f[3][7]=416;f[3][8]=554;f[3][9]=722;f[3][10]=896;f[3][11]=1064;f[3][12]=1248;f[3][13]=1512;f[3][14]=1746;f[3][15]=2016;f[3][16]=2264;f[3][17]=2600;f[3][18]=2888;f[3][19]=3218;f[3][20]=3584;f[3][21]=3912;f[3][22]=4344;f[3][23]=4712;f[3][24]=5138;f[3][25]=5612;f[3][26]=6062;f[3][27]=6536;f[3][28]=6984;f[3][29]=7520;f[3][30]=8084;f[4][1]=16;f[4][2]=64;f[4][3]=144;f[4][4]=256;f[4][5]=400;f[4][6]=576;f[4][7]=784;f[4][8]=1024;f[4][9]=1296;f[4][10]=1600;f[4][11]=1936;f[4][12]=2304;f[4][13]=2704;f[4][14]=3136;f[4][15]=3600;f[4][16]=4096;f[4][17]=4624;f[4][18]=5184;f[4][19]=5776;f[4][20]=6400;f[4][21]=7056;f[4][22]=7744;f[4][23]=8464;f[4][24]=9216;f[4][25]=10000;f[4][26]=10816;f[4][27]=11664;f[4][28]=12544;f[4][29]=13456;f[4][30]=14400;f[5][1]=24;f[5][2]=96;f[5][3]=218;f[5][4]=384;f[5][5]=624;f[5][6]=880;f[5][7]=1188;f[5][8]=1572;f[5][9]=2014;f[5][10]=2496;f[5][11]=2984;f[5][12]=3520;f[5][13]=4224;f[5][14]=4870;f[5][15]=5616;f[5][16]=6336;f[5][17]=7224;f[5][18]=8056;f[5][19]=9008;f[5][20]=9984;f[5][21]=10942;f[5][22]=12080;f[5][23]=13144;f[5][24]=14326;f[5][25]=15624;f[5][26]=16896;f[5][27]=18184;f[5][28]=19488;f[5][29]=20968;f[5][30]=22480;f[6][1]=36;f[6][2]=144;f[6][3]=324;f[6][4]=576;f[6][5]=900;f[6][6]=1296;f[6][7]=1764;f[6][8]=2304;f[6][9]=2916;f[6][10]=3600;f[6][11]=4356;f[6][12]=5184;f[6][13]=6084;f[6][14]=7056;f[6][15]=8100;f[6][16]=9216;f[6][17]=10404;f[6][18]=11664;f[6][19]=12996;f[6][20]=14400;f[6][21]=15876;f[6][22]=17424;f[6][23]=19044;f[6][24]=20736;f[6][25]=22500;f[6][26]=24336;f[6][27]=26244;f[6][28]=28224;f[6][29]=30276;f[6][30]=32400;f[7][1]=48;f[7][2]=192;f[7][3]=432;f[7][4]=768;f[7][5]=1224;f[7][6]=1740;f[7][7]=2356;f[7][8]=3102;f[7][9]=3954;f[7][10]=4896;f[7][11]=5872;f[7][12]=6960;f[7][13]=8280;f[7][14]=9564;f[7][15]=11016;f[7][16]=12456;f[7][17]=14160;f[7][18]=15816;f[7][19]=17666;f[7][20]=19584;f[7][21]=21500;f[7][22]=23688;f[7][23]=25808;f[7][24]=28122;f[7][25]=30624;f[7][26]=33120;f[7][27]=35652;f[7][28]=38266;f[7][29]=41144;f[7][30]=44076;f[8][1]=64;f[8][2]=256;f[8][3]=576;f[8][4]=1024;f[8][5]=1600;f[8][6]=2304;f[8][7]=3136;f[8][8]=4096;f[8][9]=5184;f[8][10]=6400;f[8][11]=7744;f[8][12]=9216;f[8][13]=10816;f[8][14]=12544;f[8][15]=14400;f[8][16]=16384;f[8][17]=18496;f[8][18]=20736;f[8][19]=23104;f[8][20]=25600;f[8][21]=28224;f[8][22]=30976;f[8][23]=33856;f[8][24]=36864;f[8][25]=40000;f[8][26]=43264;f[8][27]=46656;f[8][28]=50176;f[8][29]=53824;f[8][30]=57600;
	f[7][27]=35664;f[7][29]=41200;
    int t=1;
    scanf("%d",&t);
    for(cas=1;cas<=t;cas++)
    {
        for(n=1;n<=8;n++)
            for(r=1;r<=30;r++)
            {
          
		        prework();
                mainwork();
                print();
            }
        
        //scanf("%d%d",&n,&r);
        //printf("%d\n",f[n][r]);
         
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/liufengwei1/article/details/107781893
今日推荐