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;
}
以下是博客签名,正文无关
本文来自博客园,作者:Wy_x,转载请在文首注明原文链接:https://www.cnblogs.com/Wy-x/articles/18704566
版权声明:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议(CC-BY-NC-SA 4.0 协议)进行许可。

浙公网安备 33010602011771号