P4162 [SCOI2009] 最长距离 题解

题目传送门:P4162 [SCOI2009] 最长距离

\(O(n^5)\) 暴力碾过,开 O2 拿到最优解 75 ms。


解法:

容易发现,从没有障碍的点开始枚举一定优于从有障碍的点开始枚举。
这个剪枝优化效果十分明显。

对于每个没有障碍的点,从这个点进行一次广搜。

然后暴力枚举从这个点开始可以到的点的最短距离的平方,取 \(\max\)

枚举结束后,把这个最大值开根号,输出,然后就没有然后了。

如果地图全为 \(1\),需要特判。


代码:

#include<bits/stdc++.h>
#define reg register
#define int long long
using namespace std; 

const int fx[4]={1,-1,0,0};
const int fy[4]={0,0,1,-1};
//每次扩展可以到的点
bool vis[35][35];
bool mp[35][35];//输入的地图
int n,m,T;

queue<pair<int,int> > q,q2;

void copy_queue()
{
	while(q.size()) q.pop();
	while(q2.size())
		q.push(q2.front()),vis[q2.front().first][q2.front().second]=1,q2.pop();
//拷贝的同时把 vis 数组也更新。

}

void bfs(int cnt)//清除 cnt 个障碍后可以到的边
{
	copy_queue();//拷贝
	
	while(q.size())
	{
		int x=q.front().first;
		int y=q.front().second;
		q.pop();
		
		for(int i=0;i<4;i++)
		{
			int xx=x+fx[i];
			int yy=y+fy[i];
			
			if(vis[xx][yy]) continue;
			if(xx<1||yy<1||xx>n||yy>m) continue;
			//不合法
			if(mp[xx][yy])//有障碍
			{
				q2.push(make_pair(xx,yy));
				//把这个坐标推入下一次广搜的初始队列
			}
			else//没有障碍
			{
				vis[xx][yy]=1;//推入点,更新 vis 数组
				q.push(make_pair(xx,yy));
			}
		}
	}
	if(cnt<T) bfs(cnt+1);//如果没有清除到 T 个障碍
	else//清除到了
	{
		while(q2.size()) q2.pop();
		//把 q2 清空,防止下次搜索出错
	}
}

int DIS(int x,int y,int i,int j)
//求两点之间距离的平方
{
	return (x-i)*(x-i)+(y-j)*(y-j);
}

signed main()
{
	cin>>n>>m>>T;
	for(int i=1;i<=n;i++)
	for(int j=1;j<=m;j++)
	{
		char c;
		cin>>c;
		mp[i][j]=c=='1';//输入
	}
	
	int ans=0;
	
	for(int i=1;i<=n;i++)//枚举每一个点
	for(int j=1;j<=m;j++)
	{
	//	if(T==0&&mp[i][j]) continue;
		if(mp[i][j]) continue;//剪枝
		memset(vis,0,sizeof(vis));//初始化 0
		vis[i][j]=1;
		q2.push(make_pair(i,j));
		bfs(mp[i][j]);//开始广搜
		//等价于 bfs(0);
		for(int x=1;x<=n;x++)
		for(int y=1;y<=m;y++)
		{
			if(!vis[x][y]) continue;
			ans=max(ans,DIS(i,j,x,y));
		}//更新最大值
	}
	if(ans==0)//如果地图全为 1
	{//特判
		//让 (1,1) 与某个点之间的障碍消除一定最优
		for(int i=1,j=T;i<=T;i++,j--)
		{
			if(i<=n&&j<=m) ans=max(ans,DIS(1,1,i,j));
			if(i<=m&&j<=n) ans=max(ans,DIS(1,1,j,i));
		}
	}
	printf("%.6lf",sqrt(ans));
	//需要把 ans(距离的平方)开根才是答案
	
	return 0;
}
posted @ 2025-02-08 16:36  Wy_x  阅读(17)  评论(0)    收藏  举报