题目大意:给出一张地图,上面有些点有障碍物,现在有T个机会能够移除障碍物,问地图上最长的欧几里得距离是多长。
思路:在原图的基础上建图,f[i]表示的是起点到这里最少需要移除多少个障碍物,然后暴力枚举起点,更新答案即可。
CODE:
#include <map> #include <queue> #include <cmath> #include <cstdio> #include <iomanip> #include <cstring> #include <iostream> #include <algorithm> #define MAX 10010 using namespace std; const int dx[] = {0,1,-1,0,0}; const int dy[] = {0,0,0,1,-1}; map<int,pair<int,int> > G; int m,n,k; int head[MAX],total; int next[MAX],aim[MAX]; bool is_block[MAX]; int f[MAX]; bool v[MAX]; char src[110][110]; int num[110][110],cnt; inline void Add(int x,int y) { next[++total] = head[x]; aim[total] = y; head[x] = total; } inline void SPFA(int start) { static queue<int> q; while(!q.empty()) q.pop(); q.push(start); memset(v,false,sizeof(v)); memset(f,0x3f,sizeof(f)); f[start] = is_block[start]; while(!q.empty()) { int x = q.front(); q.pop(); v[x] = false; for(int i = head[x]; i; i = next[i]) if(f[aim[i]] > f[x] + is_block[aim[i]]) { f[aim[i]] = f[x] + is_block[aim[i]]; if(!v[aim[i]]) { v[aim[i]] = true; q.push(aim[i]); } } } } inline double Calc(pair<int,int> p1,pair<int,int> p2) { return sqrt((double)(p1.first - p2.first) * (p1.first - p2.first) + (double)(p1.second - p2.second) * (p1.second - p2.second)); } int main() { cin >> m >> n >> k; for(int i = 1; i <= m; ++i) { scanf("%s",src[i] + 1); for(int j = 1; j <= n; ++j) { num[i][j] = ++cnt; G[cnt] = make_pair(i,j); if(src[i][j] == '1') is_block[cnt] = true; } } for(int i = 1; i <= m; ++i) for(int j = 1; j <= n; ++j) for(int k = 1; k <= 4; ++k) { int fx = i + dx[k]; int fy = j + dy[k]; if(!num[fx][fy]) continue; Add(num[i][j],num[fx][fy]); Add(num[fx][fy],num[i][j]); } double ans = .0; for(int i = 1; i <= cnt; ++i) { SPFA(i); for(int j = 1; j <= cnt; ++j) if(f[j] <= k) ans = max(ans,Calc(G[i],G[j])); } cout << fixed << setprecision(6) << ans << endl; return 0; }
原文地址:http://blog.csdn.net/jiangyuze831/article/details/40656715