标签:mes 起点 开始 algorithm tmp iostream names out air
这题有两个思路,第一个是并查集,第二是二分.我写的二分,复杂度 \(O(n^2logn)\) 可以过
二分的方法:二分高度差别.然后从某个点起点开始整个图.如果能够将所有起点覆盖,那么证明这个高度可以实现
遍历图可以用bfs实现.这题码量稍大,但思路清晰
#include <iostream>
#include <algorithm>
#include <queue>
using namespace std;
#define pp pair<int,int>
#define f first
#define s second
int n,m,grid[505][505],tot=0;
pp st;
bool vis[505][505],vis2[505][505],vis3[505][505];
int x[4] = {1,0,-1,0};
int y[4] = {0,1,0,-1};
inline bool going(int x_, int y_, int k){
return x_+x[k]>=0 && x_+x[k]<n && y_+y[k]>=0 && y_+y[k]<m;
}//没超出框吧...
inline bool check(int num){//能不能拿
int tmp = 1;//从起点开始,起点数==1
for (int i=0;i<n;i++){
for (int j=0;j<m;j++){
vis2[i][j] = vis[i][j];
vis3[i][j] = 0;
}
}
queue<pp> q;
vis3[st.f][st.s] = 1;
vis2[st.f][st.s] = 0;
q.push(st);
while(!q.empty()){
int qf = q.front().f, qs = q.front().s;q.pop();
for (int i=0;i<4;i++){
if (going(qf,qs,i)){
int to_x = qf+x[i], to_y = qs+y[i];
if (!vis3[to_x][to_y] && abs(grid[qf][qs]-grid[to_x][to_y])<=num){
vis3[to_x][to_y] = true;
q.push(make_pair(to_x,to_y));
if (vis2[to_x][to_y]){
vis2[to_x][to_y] = 0;
tmp++;//如果走到的是起点,拿到起点数++
}
}
}
}
}
return tmp == tot;
}
inline int bs(int num){//裸的二分
int l = 0,r = 1e9;
while(l!=r-1){
int mid = (l+r)/2;
if (check(mid)) r = mid;
else l = mid;
}
if (check(l)) return l;
return r;
}
inline void solve(){
cin >> n >> m;
for (int i=0;i<n;i++)
for(int j=0;j<m;j++)
cin >> grid[i][j];
for (int i=0;i<n;i++){
for(int j=0;j<m;j++){
cin >> vis[i][j];
if (vis[i][j]){
st = make_pair(i,j);
tot++;
}
}
}
cout << bs(tot);
}
int main(){
solve();
return 0;
}
并查集思路待填充
标签:mes 起点 开始 algorithm tmp iostream names out air
原文地址:https://www.cnblogs.com/DannyXu/p/12536350.html