ACM HDOJ 1045 (Fire Net)

来源:互联网 发布:淘宝搜索代码生成器 编辑:程序博客网 时间:2024/05/21 09:05

题目链接 http://acm.hdu.edu.cn/showproblem.php?pid=1045

思路一 深度优先搜索

这个应该最容易想到了,从左上开始,按列搜索,到右下结束,具体的搜索顺序如下图


思路二 二分图的最大匹配

 一行拆成多行,一列拆成多列
 以下图为例
.X..
 ....
XX..
....

按行排号(左集)
1X22
3333
XX44
5555
 
按列排号(右集)
1X56
1356
XX56
2456

找到左集和右集中有交叉的情况
左 -> 右
1 -> 1
2 -> 5
2 -> 6
3 -> 1
3 -> 3
3 -> 5
3 -> 6
4 -> 5
4 -> 6
5 -> 2
5 -> 4
5 -> 5
5 -> 6

然后二分匹配,得到最大匹配为
1 -> 1
2 -> 5
3 -> 3
4 -> 6
5 -> 2

则放置碉堡的结果就是
OXO.
.O..
XX.O
O...

程序一 深度优先搜索

import java.util.Scanner;public class Main {public static void main(String[] args) {Scanner scn = new Scanner(System.in);while (scn.hasNext()) {int height = Integer.parseInt(scn.next());int width = height;if (0 == height) {break;}Search search = new Search(height, width, 0, 0);for (int i = 0; i < height; ++i) {search.setMatrixLine(i, scn.next().toCharArray());}search.beginSearch();System.out.println(search.getMaxNumber());}scn.close();}}class Search {private int height;private int width;private char[][] matrix;private int startX;private int startY;private int maxNumber;public Search(int height, int width, int startX, int startY) {this.height = height;this.width = width;matrix = new char[height][width];this.startX = startX;this.startY = startY;maxNumber = 0;}public void beginSearch() {dfs(startX, startY, 0);}private void dfs(int x, int y, int number) {if (x == height - 1 && y == width - 1) {if ('.' == matrix[x][y] && isValid(x, y)) {++number;}if (number > maxNumber) {maxNumber = number;}return;}if ('X' == matrix[x][y] || !isValid(x, y)) {if (y < width - 1) {dfs(x, y + 1, number);} else {dfs(x + 1, 0, number);}} else {matrix[x][y] = '*';if (y < width - 1) {dfs(x, y + 1, number + 1);} else {dfs(x + 1, 0, number + 1);}matrix[x][y] = '.';if (y < width - 1) {dfs(x, y + 1, number);} else {dfs(x + 1, 0, number);}}return;}private boolean isValid(int x, int y) {for (int i = x - 1; i >= 0; --i) {if ('X' == matrix[i][y]) {break;}if ('*' == matrix[i][y]) {return false;}}for (int j = y - 1; j >= 0; --j) {if ('X' == matrix[x][j]) {break;}if ('*' == matrix[x][j]) {return false;}}return true;}public void setMatrixLine(int line, char[] ch) {matrix[line] = ch;}public int getMaxNumber() {return maxNumber;}}

程序二 匈牙利算法 DFS

import java.util.Arrays;import java.util.Scanner;public class Main {public static void main(String[] args) {Scanner scn = new Scanner(System.in);while (scn.hasNext()) {int height = Integer.parseInt(scn.next());int width = height;if (0 == height) {break;}char[][] city = new char[height][width];int[][] left = new int[height][width];for (int i = 0; i < height; ++i) {city[i] = scn.next().toCharArray();}int leftSetNumber = 0;for (int i = 0; i < height; ++i) { // 按行if ('.' == city[i][0]) {left[i][0] = ++leftSetNumber;} else {++leftSetNumber;}boolean flag = true;for (int j = 1; j < width; ++j) {if ('.' == city[i][j]) {if (flag) {left[i][j] = leftSetNumber;} else {left[i][j] = ++leftSetNumber;flag = true;}} else {flag = false;}}}int rightSetNumber = 0;int[][] right = new int[height][width];for (int j = 0; j < height; ++j) { // 按列if ('.' == city[0][j]) {right[0][j] = ++rightSetNumber;} else {++rightSetNumber;}boolean flag = true;for (int i = 1; i < width; ++i) {if ('.' == city[i][j]) {if (flag) {right[i][j] = rightSetNumber;} else {right[i][j] = ++rightSetNumber;flag = true;}} else {flag = false;}}}Hungary hungary = new Hungary(leftSetNumber, rightSetNumber);for (int i = 0; i < height; ++i) {for (int j = 0; j < width; ++j) {if (0 != left[i][j] && 0 != right[i][j]) {hungary.addEdge(left[i][j] - 1, right[i][j] - 1);}}}System.out.println(hungary.maxMatch());}scn.close();}}class Hungary {private int leftSetNumber;private int rightSetNumber;private boolean[][] matrix;private int[] leftResult;private int[] rightResult;private boolean[] rightUsed;private boolean searchPath(int left) {for (int right = 0; right < rightSetNumber; ++right) {if (matrix[left][right] && !rightUsed[right]) {rightUsed[right] = true;if (-1 == rightResult[right] || searchPath(rightResult[right])) {rightResult[right] = left;leftResult[left] = right;return true;}}}return false;}public Hungary(int leftSetNumber, int rightSetNumber) {this.leftSetNumber = leftSetNumber;this.rightSetNumber = rightSetNumber;matrix = new boolean[leftSetNumber][rightSetNumber];leftResult = new int[leftSetNumber];rightResult = new int[rightSetNumber];rightUsed = new boolean[rightSetNumber];}public void addEdge(int left, int right) {matrix[left][right] = true;}public int maxMatch() {Arrays.fill(leftResult, -1);Arrays.fill(rightResult, -1);Arrays.fill(rightUsed, false);int count = 0;for (int left = 0; left < leftSetNumber; ++left) {if (-1 == leftResult[left]) {Arrays.fill(rightUsed, false);if (searchPath(left)) {++count;}}}return count;}}

程序三 匈牙利算法 BFS

import java.util.Arrays;import java.util.LinkedList;import java.util.Queue;import java.util.Scanner;public class Main {public static void main(String[] args) {Scanner scn = new Scanner(System.in);while (scn.hasNext()) {int height = Integer.parseInt(scn.next());int width = height;if (0 == height) {break;}char[][] city = new char[height][width];int[][] left = new int[height][width];for (int i = 0; i < height; ++i) {city[i] = scn.next().toCharArray();}int leftSetNumber = 0;for (int i = 0; i < height; ++i) { // 按行if ('.' == city[i][0]) {left[i][0] = ++leftSetNumber;} else {++leftSetNumber;}boolean flag = true;for (int j = 1; j < width; ++j) {if ('.' == city[i][j]) {if (flag) {left[i][j] = leftSetNumber;} else {left[i][j] = ++leftSetNumber;flag = true;}} else {flag = false;}}}int rightSetNumber = 0;int[][] right = new int[height][width];for (int j = 0; j < height; ++j) { // 按列if ('.' == city[0][j]) {right[0][j] = ++rightSetNumber;} else {++rightSetNumber;}boolean flag = true;for (int i = 1; i < width; ++i) {if ('.' == city[i][j]) {if (flag) {right[i][j] = rightSetNumber;} else {right[i][j] = ++rightSetNumber;flag = true;}} else {flag = false;}}}Hungary hungary = new Hungary(leftSetNumber, rightSetNumber);for (int i = 0; i < height; ++i) {for (int j = 0; j < width; ++j) {if (0 != left[i][j] && 0 != right[i][j]) {hungary.addEdge(left[i][j] - 1, right[i][j] - 1);}}}System.out.println(hungary.maxMatch());}scn.close();}}class Hungary {private int leftSetNumber;private int rightSetNumber;private boolean[][] matrix;private int[] leftResult;private int[] rightResult;private boolean[] rightUsed;private int[] preLeft;public Hungary(int leftSetNumber, int rightSetNumber) {this.leftSetNumber = leftSetNumber;this.rightSetNumber = rightSetNumber;matrix = new boolean[leftSetNumber][rightSetNumber];leftResult = new int[leftSetNumber];rightResult = new int[rightSetNumber];rightUsed = new boolean[rightSetNumber];preLeft = new int[leftSetNumber];}public void addEdge(int left, int right) {matrix[left][right] = true;}public int maxMatch() {Arrays.fill(leftResult, -1);Arrays.fill(rightResult, -1);Arrays.fill(preLeft, -1);int count = 0;for (int i = 0; i < leftSetNumber; ++i) {if (-1 == leftResult[i]) {Queue<Integer> queue = new LinkedList<Integer>();queue.offer(i);boolean hasAP = false;Arrays.fill(rightUsed, false);while (!queue.isEmpty() && !hasAP) {int left = queue.poll();for (int right = 0; right < rightSetNumber && !hasAP; ++right) {if (matrix[left][right] && !rightUsed[right]) {rightUsed[right] = true;queue.offer(rightResult[right]);if (0 <= rightResult[right]) {preLeft[rightResult[right]] = left;} else {hasAP = true;int currentLeft = left;int currentRight = right;while (-1 != currentLeft) {int lastRight = leftResult[currentLeft];leftResult[currentLeft] = currentRight;rightResult[currentRight] = currentLeft;currentLeft = preLeft[currentLeft];currentRight = lastRight;}}}}}if (-1 != leftResult[i]) {++count;}}}return count;}}

程序四 Hopcroft-Carp 算法

import java.util.Arrays;import java.util.LinkedList;import java.util.Queue;import java.util.Scanner;public class Main {public static void main(String[] args) {Scanner scn = new Scanner(System.in);while (scn.hasNext()) {int height = Integer.parseInt(scn.next());int width = height;if (0 == height) {break;}char[][] city = new char[height][width];int[][] left = new int[height][width];for (int i = 0; i < height; ++i) {city[i] = scn.next().toCharArray();}int leftSetNumber = 0;for (int i = 0; i < height; ++i) { // 按行if ('.' == city[i][0]) {left[i][0] = ++leftSetNumber;} else {++leftSetNumber;}boolean flag = true;for (int j = 1; j < width; ++j) {if ('.' == city[i][j]) {if (flag) {left[i][j] = leftSetNumber;} else {left[i][j] = ++leftSetNumber;flag = true;}} else {flag = false;}}}int rightSetNumber = 0;int[][] right = new int[height][width];for (int j = 0; j < height; ++j) { // 按列if ('.' == city[0][j]) {right[0][j] = ++rightSetNumber;} else {++rightSetNumber;}boolean flag = true;for (int i = 1; i < width; ++i) {if ('.' == city[i][j]) {if (flag) {right[i][j] = rightSetNumber;} else {right[i][j] = ++rightSetNumber;flag = true;}} else {flag = false;}}}HopcroftCarp hopcroftCarp = new HopcroftCarp(leftSetNumber,rightSetNumber);for (int i = 0; i < height; ++i) {for (int j = 0; j < width; ++j) {if (0 != left[i][j] && 0 != right[i][j]) {hopcroftCarp.addEdge(left[i][j] - 1, right[i][j] - 1);}}}System.out.println(hopcroftCarp.maxMatch());}scn.close();}}class HopcroftCarp {private final int INF = Integer.MAX_VALUE / 2;private int leftSetNumber;private int rightSetNumber;private boolean[][] matrix;private int[] leftResult;private int[] rightResult;private boolean[] rightUsed;private int[] leftGradation;private int[] rightGradation;private int gradation;private boolean searchPath() {Arrays.fill(leftGradation, -1);Arrays.fill(rightGradation, -1);gradation = INF;Queue<Integer> queue = new LinkedList<Integer>();for (int left = 0; left < leftSetNumber; ++left) {if (-1 == leftResult[left]) {queue.offer(left);++leftGradation[left];}}while (!queue.isEmpty()) {int left = queue.poll();if (leftGradation[left] > gradation) {break;}for (int right = 0; right < rightSetNumber; ++right) {if (matrix[left][right] && -1 == rightGradation[right]) {rightGradation[right] = leftGradation[left] + 1;if (-1 == rightResult[right]) {gradation = rightGradation[right];} else {leftGradation[rightResult[right]] = rightGradation[right] + 1;queue.offer(rightResult[right]);}}}}return INF != gradation;}private boolean dfs(int left) {for (int right = 0; right < rightSetNumber; right++) {if (!rightUsed[right] && matrix[left][right]&& rightGradation[right] == leftGradation[left] + 1) {rightUsed[right] = true;if (-1 != rightResult[right]&& rightGradation[right] == gradation) {continue;}if (-1 == rightResult[right] || dfs(rightResult[right])) {rightResult[right] = left;leftResult[left] = right;return true;}}}return false;}public HopcroftCarp(int leftSetNumber, int rightSetNumber) {this.leftSetNumber = leftSetNumber;this.rightSetNumber = rightSetNumber;matrix = new boolean[leftSetNumber][rightSetNumber];leftResult = new int[leftSetNumber];rightResult = new int[rightSetNumber];rightUsed = new boolean[rightSetNumber];leftGradation = new int[leftSetNumber];rightGradation = new int[rightSetNumber];gradation = INF;}public void addEdge(int left, int right) {matrix[left][right] = true;}public int maxMatch() {Arrays.fill(leftResult, -1);Arrays.fill(rightResult, -1);int count = 0;while (searchPath()) {Arrays.fill(rightUsed, false);for (int left = 0; left < leftSetNumber; ++left) {if (-1 == leftResult[left] && dfs(left)) {++count;}}}return count;}}

0 0
原创粉丝点击