一点疑惑
  • 板块P1783 海滩防御
  • 楼主Nazq
  • 当前回复0
  • 已保存回复0
  • 发布时间2024/3/17 21:33
  • 上次更新2024/3/18 11:39:08
查看原帖
一点疑惑
1051166
Nazq楼主2024/3/17 21:33

我是二分 ++ 并查集。 并查集是枚举任意两点,

如果距离够,就把他们的行连起来,

最后以 00 是否可以走到 nn 来判断是否封锁, 但不知道为什么只得了 30 分,其他全 WA。

感觉思路错了,但想不到 hack 数据。

#include <cstdio>
#include <numeric>
#include <cmath>
#include <algorithm>
namespace Use{
	using std::iota;
	using std::sqrt;
	using std::max;
	using std::min;
	using std::fill;
}
using namespace Use;
inline void read(int& x){
    bool f=1;x=0;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-') f=!f;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
    x=(f?x:-x);
}
const int N=1000,M=805;
const double eps=1e-4,Inf=0x3f3f3f3f;
int n,m,x[M],y[M],f[N],maxn_x,maxn_y,minn_x=Inf,minn_y=Inf;
double maxn,dis[N][N];
double L(const int& x1,const int& y1,const int& x2,const int& y2){ return sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2)); }
void Read(){
	read(n);read(m);
	for(int i=1;i<=m;++i){
		read(x[i]);read(y[i]);
		//printf("%d %d\n",x[i],y[i]);
		maxn_x=max(maxn_x,x[i]);
		maxn_y=max(maxn_y,y[i]);
		minn_x=min(minn_x,x[i]);
		minn_y=min(minn_y,y[i]);
	}
	maxn=L(minn_x,minn_y,maxn_x,maxn_y);
	//printf("%.2lf\n",maxn);
}
int find_set(int v){
	if(v!=f[v])
		f[v]=find_set(f[v]);
	return f[v];
}
void merge(int x,int y){
	x=find_set(x);y=find_set(y);
	if(x!=y)
		f[x]=y;
}
bool Check(const double& base){
	double len=base*2;
	iota(f,f+n+1,0);
	for(int i=1;i<=m;++i){
		if(x[i]<=base)merge(0,x[i]);
		if(n-x[i]<=base)merge(x[i],n);
		for(int j=i+1;j<=m;++j){
			if(dis[i][j]<=len)
				merge(x[i],x[j]);
		}
	}
	if(find_set(0)==find_set(n))return true;
	else return false;
}
void ErFen(double l,double r){
	double mid;
	while(r-l>eps){
		mid=(l+r)/2;
		if(Check(mid))r=mid;
		else l=mid;
	}
	printf("%.2lf",l);
}
int main(){
	Read();
	for(int i=1;i<=m;++i){
		for(int j=i+1;j<=m;++j){
			dis[j][i]=dis[i][j]=L(x[i],y[i],x[j],y[j]);
		}
	}
	ErFen(1,maxn);
	return 0;
}
2024/3/17 21:33
加载中...