luogu P2124 奶牛美容
首先数据范围那么小,那么算法也是相当暴力的。
对于一个点(x, y)所属的联通块,预处理出从这个点出发到这个块外的所有点的曼哈顿距离。复杂度O(n4)。
然后求答案:最少答案不一定是三个联通块两两相连,可能是两个联通块之间搭了个桥,然后第三个联通块连接在这个桥上。因此我们像floyd一样,枚举中间点,然后用dis[1][i][j] + dis[2][i][j] + dis[3][i][j]尝试更新答案。
刚开始我因为没有考虑到上面的情况,预处理出每一个点到其他联通块上的点的距离,然后排序,像最小生成树一样贪心取边。导致WA了几个点。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<cstdio> 2 #include<iostream> 3 #include<cmath> 4 #include<algorithm> 5 #include<cstring> 6 #include<cstdlib> 7 #include<cctype> 8 #include<vector> 9 #include<stack> 10 #include<queue> 11 using namespace std; 12 #define enter puts("") 13 #define space putchar(' ') 14 #define Mem(a, x) memset(a, x, sizeof(a)) 15 #define rg register 16 typedef long long ll; 17 typedef double db; 18 const int INF = 0x3f3f3f3f; 19 const db eps = 1e-8; 20 const int maxn = 55; 21 inline ll read() 22 { 23 ll ans = 0; 24 char ch = getchar(), last = ' '; 25 while(!isdigit(ch)) {last = ch; ch = getchar();} 26 while(isdigit(ch)) {ans = ans * 10 + ch - '0'; ch = getchar();} 27 if(last == '-') ans = -ans; 28 return ans; 29 } 30 inline void write(ll x) 31 { 32 if(x < 0) x = -x, putchar('-'); 33 if(x >= 10) write(x / 10); 34 putchar(x % 10 + '0'); 35 } 36 37 int n, m; 38 char a[maxn][maxn]; 39 int vis[maxn][maxn], cnt = 0; 40 41 const int dx[] = {-1, 0, 1, 0}, dy[] = {0, 1, 0, -1}; 42 void dfs(int x, int y, int flg) 43 { 44 vis[x][y] = flg; 45 for(int i = 0; i < 4; ++i) 46 { 47 int newx = x + dx[i], newy = y + dy[i]; 48 if(newx > 0 && newx <= n && newy > 0 && newy <= m && 49 a[newx][newy] == 'X' && !vis[newx][newy]) 50 dfs(newx, newy, flg); 51 } 52 } 53 54 int dis[4][maxn][maxn], f[maxn][maxn]; 55 void solve(int flg, int x, int y) 56 { 57 for(int i = 1; i <= n; ++i) 58 for(int j = 1; j <= m; ++j) 59 dis[flg][i][j] = min(dis[flg][i][j], abs(i - x) + abs(j - y)); 60 } 61 62 int main() 63 { 64 n = read(); m = read(); 65 for(int i = 1; i <= n; ++i) scanf("%s", a[i] + 1); 66 for(int i = 1; i <= n; ++i) 67 for(int j = 1; j <= m; ++j) 68 if(a[i][j] == 'X' && !vis[i][j]) 69 dfs(i, j, ++cnt); 70 Mem(dis, 0x3f); 71 for(int i = 1; i <= n; ++i) 72 for(int j = 1; j <= m; ++j) 73 if(a[i][j] == 'X') solve(vis[i][j], i, j); 74 Mem(f, 0x3f); 75 for(int i = 1; i <= n; ++i) 76 for(int j = 1; j <= m; ++j) if(a[i][j] == 'X') 77 { 78 f[vis[i][j]][1] = min(f[vis[i][j]][1], dis[1][i][j]); 79 f[vis[i][j]][2] = min(f[vis[i][j]][2], dis[2][i][j]); 80 f[vis[i][j]][3] = min(f[vis[i][j]][3], dis[3][i][j]); 81 f[1][vis[i][j]] = f[vis[i][j]][1]; 82 f[2][vis[i][j]] = f[vis[i][j]][2]; 83 f[3][vis[i][j]] = f[vis[i][j]][3]; 84 } 85 int ans = min(f[1][2] + f[2][3], min(f[1][3] + f[1][2], f[1][3] + f[2][3])); 86 for(int i = 1; i <= n; ++i) 87 for(int j = 1; j <= m; ++j) 88 ans = min(ans, dis[1][i][j] + dis[2][i][j] + dis[3][i][j]); 89 write(ans - 2); enter; 90 return 0; 91 }