【洛谷4212】外太空旅行(模拟退火)
大致题意: 给你一张图,让你从中选取最多的点,使这些点所构成的是完全图。
模拟退火
这道题可以用模拟退火来乱搞(或者随机化+\(dfs\)?)。
大体就是搞一个序列,定义其价值为从左往右、见到合法点立刻选所能选出的点数。
然后模拟退火,求出最大价值即为答案。
代码
#include<bits/stdc++.h>
#define Tp template<typename Ty>
#define Ts template<typename Ty,typename... Ar>
#define Reg register
#define RI Reg int
#define Con const
#define CI Con int&
#define I inline
#define W while
#define N 50
#define swap(x,y) (x^=y^=x^=y)
#define Gmax(x,y) (x<(y)&&(x=(y)))
using namespace std;
int n,f[N+5][N+5];
class SimulatedAnnealing//模拟退火
{
private:
#define SA_TIME 100
int ans,s[N+5],vis[N+5];
I int Calc()//求出序列价值
{
RI i,j,res=0;for(i=1;i<=n;++i)
{
for(j=1;j^i;++j) if(vis[j]&&!f[s[i]][s[j]]) break;
i^j?vis[i]=0:(++res,vis[i]=1);
}return res;
}
I void Work()//模拟退火
{
RI i,x,y,res,nres;for(i=1;i<=n;++i) s[i]=i;random_shuffle(s+1,s+n+1),res=Calc(),Gmax(ans,res);//随机初始序列
for(double tt=1e7;tt>1e-3;tt*=0.995)
{
W((x=rand()%n+1)==(y=rand()%n+1));swap(s[x],s[y]),nres=Calc(),Gmax(ans,nres);
(nres>res||exp((res-nres)/tt)>1.0*rand()/RAND_MAX)?res=nres:swap(s[x],s[y]);
}
}
public:
I void Solve() {srand(20030909);for(RI i=1;i<=SA_TIME;++i) Work();printf("%d",ans);}
}S;
int main()
{
RI i,x,y;scanf("%d",&n);W(~scanf("%d%d",&x,&y)) f[x][y]=f[y][x]=1;//读入,建图
return S.Solve(),0;
}
待到再迷茫时回头望,所有脚印会发出光芒