题意:给你一个点集,让你选出最多的点同时保证任意两个点之间距离不能超过d。
一开始一看见n<=100以为直接暴力加入,然后每一次在已经加入的里面比较,结果WA了。。其实挺明显的,肯定不是最优的啊= =,要保证正确性只能2^100。。。
所以就懵逼了,题解是随机化一个序列以后贪心来,感觉整个人都不好了。。还有这种选学算法= =
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<bitset>
#define fo(i,a,b) for(int i=a;i<=b;i++)
#define fd(i,a,b) for(int i=a;i>=b;i--)
using namespace std;
const int N=105+5;
int n,m;
int d,w[N];
bitset<N>ans,now;
bool f[N][N],vis[N];
struct node
{
int x,y;
}a[N];
inline int getdis(node a,node b)
{
return (a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y);
}
inline void Rand()
{
fo(i,1,n)swap(w[i],w[rand()%n+1]);
}
inline void solve()
{
memset(vis,0,sizeof(vis));
now.reset();
fo(i,1,n)
if (!vis[i])
{
now.set(w[i]);
fo(j,i+1,n)
if (!f[w[i]][w[j]])vis[j]=1;
}
if (now.count()>ans.count())ans=now;
}
int main()
{
scanf("%d%d",&n,&d);
fo(i,1,n)
{
scanf("%d%d",&a[i].x,&a[i].y);
w[i]=i;
}
fo(i,1,n-1)
fo(j,i+1,n)
if (getdis(a[i],a[j])<=d*d)f[i][j]=f[j][i]=1;
fo(i,1,1000)Rand(),solve();
printf("%d\n",ans.count());
fo(i,1,n)if (ans[i])printf("%d ",i);
}