找不同,在一定范围内找出不同数最小的数组。
题目:
In the attic of your house you found an M×N board, divided into MN unit squares. Some of the squares are black and the others are white. You decided that you will make a chessboard out of the board by cutting out an 8×8 region and throwing away the rest of the board.
The only problem is that the board is not painted in the alternate black/white pattern you need for the chessboard. Thus after you cut out the 8×8 chessboard, you will have to repaint some of the squares. Of course, you can pick which 8×8 region to cut out.
You are given the current colors of the squares as a String[] board. Character c in element r of board is 'W' if the cell at coordinates (r,c) is white, and 'B' if it is black. Your task is to find the minimum number of squares you will need to repaint after cutting out the 8×8 region.
Definition
Class: RepaintTheChessboard
Method: minimumChanges
Parameters: String[]
Returns: int
Method signature: int minimumChanges(String[] board)
(be sure your method is public)
Notes
- On a correctly colored chessboard each square is either black or white, and no two squares that share a side have the same color.
(Note that according to this definition there are two valid colorings: one with a white, the other with a black square in the upper left corner.)
Constraints
- board will contain between 8 and 50 elements, inclusive.
- Each element of board will contain between 8 and 50 characters, inclusive.
- All elements of board will have the same length.
- Each character in each element of board will be either 'B' or 'W'.
Examples
0)
{"BWBWBWBW",
"WBWBWBWB",
"BWBWBWBW",
"WBWBWBWB",
"BWBWBWBW",
"WBWBWBWB",
"BWBWBWBW",
"WBWBWBWB"}
Returns: 0
This is a perfect chessboard, no repainting (and no cutting) necessary.
1)
{"WBWBWBWB",
"BWBWBWBW",
"WBWBWBWB",
"BWBBBWBW",
"WBWBWBWB",
"BWBWBWBW",
"WBWBWBWB",
"BWBWBWBW"}
Returns: 1
This is almost a perfect chessboard, except for one square.
(Using 0-based indices, the incorrectly colored square is element 3, character 3 of board.)
2)
{"BBBBBBBBBBBBBBBBBBBBBBB",
"BBBBBBBBBBBBBBBBBBBBBBB",
"BBBBBBBBBBBBBBBBBBBBBBB",
"BBBBBBBBBBBBBBBBBBBBBBB",
"BBBBBBBBBBBBBBBBBBBBBBB",
"BBBBBBBBBBBBBBBBBBBBBBB",
"BBBBBBBBBBBBBBBBBBBBBBB",
"BBBBBBBBBBBBBBBBBBBBBBB",
"BBBBBBBBBBBBBBBBBBBBBBW"}
Returns: 31
If we take the 8×8 piece in the lower right corner, we will have one white square, and we will only need 31 more.
3)
{"BBBBBBBBBB",
"BBWBWBWBWB",
"BWBWBWBWBB",
"BBWBWBWBWB",
"BWBWBWBWBB",
"BBWBWBWBWB",
"BWBWBWBWBB",
"BBWBWBWBWB",
"BWBWBWBWBB",
"BBBBBBBBBB"}
Returns: 0
Here we have a perfect chessboard in the middle of the given board.
4)
{"WBWBWBWB",
"BWBWBWBW",
"WBWBWBWB",
"BWBBBWBW",
"WBWBWBWB",
"BWBWBWBW",
"WBWBWWWB",
"BWBWBWBW"}
Returns: 2
For this board the minimum number of changes is 2: We need to change one black square into a white one, and one white square into a black one.
5)
{"BWWBWWBWWBWW",
"BWWBWBBWWBWW",
"WBWWBWBBWWBW",
"BWWBWBBWWBWW",
"WBWWBWBBWWBW",
"BWWBWBBWWBWW",
"WBWWBWBBWWBW",
"BWWBWBWWWBWW",
"WBWWBWBBWWBW",
"BWWBWBBWWBWW",
"WBWWBWBBWWBW"}
Returns: 15
This problem statement is the exclusive and proprietary property of TopCoder, Inc. Any unauthorized use or reproduction of this information without the prior written consent of TopCoder, Inc. is strictly prohibited. (c)2003, TopCoder, Inc. All rights reserved.
题目的大概意思是有一块 M×N的有黑白颜色的地板,颜色排列如如字符串数组board[]所示。先要求在这个MxN的地板中选出8x8的矩形,并且这块8x8矩形要上下前后黑白相间,原来不是黑白相间的话就要改动。求选取改动最小的8x8矩形,返回需要改动的数目。
我一开始就想到最直接的方法,判断每一个字符串是不是黑白相间,不是的话计算误差率,然后根据误差率选择8x8矩形,再计算需要修改数。这是一般人的直接思维。事实证明这种思维在编程里是很不好的。我们需要用更巧妙的方法来写程序。
看了一下高人写的算法,过程大致是这样的:先生成一个和board数组同大小的二维数组realBoard[][],然后比较board和realBoard的不同数(就是需要修改的数目),记录下来。记得只比较8x8范围,所以要比较所有的8x8范围。
算法如下:
public class RepaintTheChessboard {
public static void main(String[] args) {
String[] board = { "BWWBWWBWWBWW", "BWWBWBBWWBWW", "WBWWBWBBWWBW",
"BWWBWBBWWBWW", "WBWWBWBBWWBW", "BWWBWBBWWBWW", "WBWWBWBBWWBW",
"BWWBWBWWWBWW", "WBWWBWBBWWBW", "BWWBWBBWWBWW", "WBWWBWBBWWBW" };
RepaintTheChessboard rc = new RepaintTheChessboard();
int count = rc.minimumChanges(board);
System.out.println(count);
}
public int minimumChanges(String[] board) {
int min = Integer.MAX_VALUE;
int leng1 = board.length; // 字符串行数leng1
int leng2 = board[0].length(); // 字符串列数leng2
char real = board[0].charAt(0); // 首字母
char[][] realBoard = new char[leng1][leng2]; // 正确的数组
realBoard[0][0] = real;
// 初始化一个正确的数组
for (int i = 0; i < leng1; i++) {
if (i != 0)
realBoard[i][0] = (realBoard[i - 1][0] == 'W' ? 'B' : 'W');
for (int j = 1; j < leng2; j++) {
realBoard[i][j] = (realBoard[i][j - 1] == 'W' ? 'B' : 'W');
}
}
// 将要计算的字符串数组与正确的数组比较(只比较8*8范围) 记录不相等的个数min
for (int i = 0; i < leng1; ++i) {
for (int j = 0; j < leng2; ++j) {
int r = i, c = j;
int lastR = r + 7;
int lastC = c + 7;
if (lastR >= leng1 || lastC >= leng2)
break;
int best = 0;
for (int k = r; k <= lastR; ++k) {
for (int l = c; l <= lastC; ++l) {
if (board[k].charAt(l) != realBoard[k][l]) {
++best;
}
}
}
min = Math.min(min, best);
}
}
// 再对比一次,因为正确的数组有两种情况,例如BWBWBWBW是可以的 那么WBWBWBWB也是正确的.
for (int i = 0; i < leng1; ++i) {
for (int j = 0; j < leng2; ++j) {
int r = i, c = j;
int lastR = r + 7;
int lastC = c + 7;
if (lastR >= leng1 || lastC >= leng2)
break;
int best = 0;
for (int k = r; k <= lastR; ++k) {
for (int l = c; l <= lastC; ++l) {
if (board[k].charAt(l) == realBoard[k][l]) {
++best;
}
}
}
min = Math.min(min, best);
}
}
return min;
}
}
总结:我还是太年轻啦,需要好好转变自己的思维。明天开始看算法导论。
注:源码来自TopCoder上某高人。