题目链接:
听说最近两斑点的奶牛最受欢迎,约翰立即购进了一批两斑点牛。
不幸的是,时尚潮流往往变化很快,当前最受欢迎的牛变成了一斑点牛。
约翰希望通过给每头奶牛涂色,使得它们身上的两个斑点能够合为一个斑点,让它们能够更加时尚。
牛皮可用一个 N×M 的字符矩阵来表示,如下所示:
................
..XXXX....XXX...
...XXXX....XX...
.XXXX......XXX..
........XXXXX...
.........XXX....
其中,X 表示斑点部分。
如果两个 X 在垂直或水平方向上相邻(对角相邻不算在内),则它们属于同一个斑点,由此看出上图中恰好有两个斑点。
约翰牛群里所有的牛都有两个斑点。
约翰希望通过使用油漆给奶牛尽可能少的区域内涂色,将两个斑点合为一个。
在上面的例子中,他只需要给三个 .. 区域内涂色即可(新涂色区域用 ∗ 表示):
................
..XXXX....XXX...
...XXXX*...XX...
.XXXX..**..XXX..
........XXXXX...
.........XXX....
请帮助约翰确定,为了使两个斑点合为一个,他需要涂色区域的最少数量。
代码:
import java.util.*;
public class Main {
static int n, m;
static int N = 100;
static int[] xx = {1,0,-1,0};
static int[] yy = {0,1,0,-1};
static char[][] s = new char[N][N];
static boolean[][] f = new boolean[N][N];
static List<node>[] q = new ArrayList[2];
static class node{
int x, y;
public node(int x, int y) {
this.x = x;
this.y = y;
}
}
public static void bfs(int x, int y, int cnt) {
f[x][y] = true;
q[cnt].add(new node(x, y));
for(int i = 0; i < 4; i ++)
{
int x1 = x + xx[i];
int y1 = y + yy[i];
if(0 <= x1 && x1 < n && 0 <= y1 && y1 < m && !f[x1][y1] && s[x1][y1] == 'X')
bfs(x1, y1, cnt);
}
}
public static void main(String[] args) {
Scanner inScanner = new Scanner(System.in);
n = inScanner.nextInt();
m = inScanner.nextInt();
for(int i = 0; i < q.length; i ++)
q[i] = new ArrayList<>();
for(int i = 0; i < n; i ++)
{
String ss;
ss = inScanner.next();
for(int j = 0; j < m; j ++)
s[i][j] = ss.charAt(j);
}
int cnt = 0;
for(int i = 0; i < n; i ++)
{
for(int j = 0; j < m; j ++)
{
if(!f[i][j] && s[i][j] == 'X')
{
bfs(i, j, cnt);
cnt ++;
}
}
}
inScanner.close();
int ans = 100000;
for(node a : q[0])
for(node b : q[1])
{
int t = Math.abs(a.x - b.x) + Math.abs(a.y - b.y) - 1;
ans = Math.min(ans, t);
}
System.out.println(ans);
}
}
/*
*
6 16
................
..XXXX....XXX...
...XXXX....XX...
.XXXX......XXX..
........XXXXX...
.........XXX....
**/