E. Three States
Problem's Link
Mean:
在一个N*M的方格内,有五种字符:'1','2','3','.','#'.
现在要你在'.'的地方修路,使得至少存在一个块'1','2'和'3'是连通的.
问:最少需要修多少个'.'的路.
analyse:
想法题,想到了就很简单.
直接暴力枚举每个国家到每个可达的点的最小代价,然后计算总和取最小值.
dis[k][x][y]表示第k个国家到达坐标(x,y)的点的最小代价.
Time complexity: O(N)
view code
/*
* -----------------------------------------------------------------
* Copyright (c) 2015 crazyacking All rights reserved.
* -----------------------------------------------------------------
* Author: crazyacking
*/
#include <queue>
#include <cstdio>
#include <set>
#include <string>
#include <stack>
#include <cmath>
#include <climits>
#include <map>
#include <cstdlib>
#include <iostream>
#include <vector>
#include <algorithm>
#include <cstring>
#define max(a,b) (a>b?a:b)
using namespace std;
typedef long long(LL);
typedef unsigned long long(ULL);
const double eps(1e-8);
const int MAXN = 1001;
char s[MAXN][MAXN];
int dx[4] = { -1,0,1,0 };
int dy[4] = { 0,-1,0,1 };
int dis[3][MAXN][MAXN];
int main()
{
ios_base::sync_with_stdio(false);
cin.tie(0);
int n, m;
while (~scanf("%d %d", &n, &m))
{
for (int i = 0; i < n; ++i)
scanf("%s", s[i]);
for (int i = 0; i < n; ++i)
for (int j = 0; j < m; ++j)
dis[0][i][j] = dis[1][i][j] = dis[2][i][j] = (int)1e8;
queue<pair<int, int> > Q;
for (int k = 0; k < 3; ++k)
{
while (!Q.empty())
Q.pop();
for (int i = 0; i < n; ++i)
{
for (int j = 0; j < m; ++j)
{
if (s[i][j] == k + '1')
{
Q.push(make_pair(i, j));
dis[k][i][j] = 0;
}
}
}
while (!Q.empty())
{
pair<int, int> now = Q.front();
Q.pop();
int x = now.first;
int y = now.second;
for (int i = 0; i < 4; ++i)
{
int xx = x + dx[i];
int yy = y + dy[i];
if (!(xx >= 0 && xx < n))continue;
if (!(yy >= 0 && yy<m))continue;
if (s[xx][yy] == '#')continue;
if (dis[k][xx][yy]>dis[k][x][y] + (s[x][y] == '.'))
{
dis[k][xx][yy] = dis[k][x][y] + (s[x][y] == '.');
Q.push(make_pair(xx, yy));
}
}
}
}
int ans = 1e9;
for (int i = 0; i < n; ++i)
{
for (int j = 0; j < m; ++j)
ans = min(ans, dis[0][i][j] + dis[1][i][j] + dis[2][i][j]+(s[i][j]=='.'));
}
if (ans >= 1e8)
puts("-1");
else
printf("%d ", ans);
}
return 0;
}
/*
*/
* -----------------------------------------------------------------
* Copyright (c) 2015 crazyacking All rights reserved.
* -----------------------------------------------------------------
* Author: crazyacking
*/
#include <queue>
#include <cstdio>
#include <set>
#include <string>
#include <stack>
#include <cmath>
#include <climits>
#include <map>
#include <cstdlib>
#include <iostream>
#include <vector>
#include <algorithm>
#include <cstring>
#define max(a,b) (a>b?a:b)
using namespace std;
typedef long long(LL);
typedef unsigned long long(ULL);
const double eps(1e-8);
const int MAXN = 1001;
char s[MAXN][MAXN];
int dx[4] = { -1,0,1,0 };
int dy[4] = { 0,-1,0,1 };
int dis[3][MAXN][MAXN];
int main()
{
ios_base::sync_with_stdio(false);
cin.tie(0);
int n, m;
while (~scanf("%d %d", &n, &m))
{
for (int i = 0; i < n; ++i)
scanf("%s", s[i]);
for (int i = 0; i < n; ++i)
for (int j = 0; j < m; ++j)
dis[0][i][j] = dis[1][i][j] = dis[2][i][j] = (int)1e8;
queue<pair<int, int> > Q;
for (int k = 0; k < 3; ++k)
{
while (!Q.empty())
Q.pop();
for (int i = 0; i < n; ++i)
{
for (int j = 0; j < m; ++j)
{
if (s[i][j] == k + '1')
{
Q.push(make_pair(i, j));
dis[k][i][j] = 0;
}
}
}
while (!Q.empty())
{
pair<int, int> now = Q.front();
Q.pop();
int x = now.first;
int y = now.second;
for (int i = 0; i < 4; ++i)
{
int xx = x + dx[i];
int yy = y + dy[i];
if (!(xx >= 0 && xx < n))continue;
if (!(yy >= 0 && yy<m))continue;
if (s[xx][yy] == '#')continue;
if (dis[k][xx][yy]>dis[k][x][y] + (s[x][y] == '.'))
{
dis[k][xx][yy] = dis[k][x][y] + (s[x][y] == '.');
Q.push(make_pair(xx, yy));
}
}
}
}
int ans = 1e9;
for (int i = 0; i < n; ++i)
{
for (int j = 0; j < m; ++j)
ans = min(ans, dis[0][i][j] + dis[1][i][j] + dis[2][i][j]+(s[i][j]=='.'));
}
if (ans >= 1e8)
puts("-1");
else
printf("%d ", ans);
}
return 0;
}
/*
*/