Suppose that we have a square city with straight streets. A map of a city is a square board with n rows and n columns, each representing a street or a piece of wall.
A blockhouse is a small castle that has four openings through which to shoot. The four openings are facing North, East, South, and West, respectively. There will be one machine gun shooting through each opening.
Here we assume that a bullet is so powerful that it can run across any distance and destroy a blockhouse on its way. On the other hand, a wall is so strongly built that can stop the bullets.
The goal is to place as many blockhouses in a city as possible so that no two can destroy each other. A configuration of blockhouses is legal provided that no two blockhouses are on the same horizontal row or vertical column in a map unless there is at least one wall separating them. In this problem we will consider small square cities (at most 4x4) that contain walls through which bullets cannot run through.
The following image shows five pictures of the same board. The first picture is the empty board, the second and third pictures show legal configurations, and the fourth and fifth pictures show illegal configurations. For this board, the maximum number of blockhouses in a legal configuration is 5; the second picture shows one way to do it, but there are several other ways.

Your task is to write a program that, given a description of a map, calculates the maximum number of blockhouses that can be placed in the city in a legal configuration.
A blockhouse is a small castle that has four openings through which to shoot. The four openings are facing North, East, South, and West, respectively. There will be one machine gun shooting through each opening.
Here we assume that a bullet is so powerful that it can run across any distance and destroy a blockhouse on its way. On the other hand, a wall is so strongly built that can stop the bullets.
The goal is to place as many blockhouses in a city as possible so that no two can destroy each other. A configuration of blockhouses is legal provided that no two blockhouses are on the same horizontal row or vertical column in a map unless there is at least one wall separating them. In this problem we will consider small square cities (at most 4x4) that contain walls through which bullets cannot run through.
The following image shows five pictures of the same board. The first picture is the empty board, the second and third pictures show legal configurations, and the fourth and fifth pictures show illegal configurations. For this board, the maximum number of blockhouses in a legal configuration is 5; the second picture shows one way to do it, but there are several other ways.

Your task is to write a program that, given a description of a map, calculates the maximum number of blockhouses that can be placed in the city in a legal configuration.
Input
The input file contains one or more map descriptions, followed by a line containing the number 0 that signals the end of the file. Each map description begins with a line containing a positive integer n that is the size of the city; n will be at most 4. The
next n lines each describe one row of the map, with a '.' indicating an open space and an uppercase 'X' indicating a wall. There are no spaces in the input file.
Output
For each test case, output one line containing the maximum number of blockhouses that can be placed in the city in a legal configuration.
Sample Input
4 .X.. .... XX.. .... 2 XX .X 3 .X. X.X .X. 3 ... .XX .XX 4 .... .... .... .... 0
Sample Output
5 1 5 2 4
解题思路:
这种解法我是看了网上的才知道的 我刚开始想的是 预处理+dfs+剪枝 尴尬的是 别人翻译完了告诉我最大就4层 无脑a就可以了。。。
我很伤心 特别伤心 不过还有这种神一样的抽象解法 一定要学一学 下面是我的理解
,
既然是二分匹配 那么先抽象成二分图 抽象:找到题意最本质的东西 然后这种本质与某个规律啊,某个图形结构,某个数学公式定理啊肯定有关联
就像这题 我们要根据题意找到最本质的东西
题意:往个格子中放老将 最多放多少个,
那么性质很明了 任意两个老将都不能对脸儿,棋盘是二维的 且保证最多
你看上面的抽象的解释 你就想这些性质能跟啥玩意对上呢
哎 你发现这怎么跟二分图有点像呢
任意棋子不能对脸---->就是任意棋子之间不发生任何冲突 二分图中的不冲突的俩俩匹配
最多放多少个棋子---->就是匈牙利算法求的最大匹配对数
最难的地方来了我要用匈牙利算法 首先得有二分图啊
还是看性质 一个棋子放在某一行和某一列的相交点 这一行和这一列不能有别人
所以先按行缩点设为左图 在按列缩点设为右图
就是找这一行或一列能连在一起的就变成一个点 ,有行和列相交的点就连上线 有线表示可以放旗子 一条线一个棋子
最后只要求出 最多能留下几条线 也就是最多有多少个匹配对 就是最后的答案
我写完发觉有100行代码 有点多 应该是我写麻烦了 对付看吧。。。。
还有如果不明白匈牙利可以看我写的过山车
import java.util.ArrayList;
import java.util.Scanner;
public class Main {
private static Scanner scanner;
private static int n;
private static char [][] arr;
private static boolean[][] graph;
private static int boy;
private static int girl;
private static int[] girl_frined;
private static boolean[] flag;
public static void main(String[] args) {
scanner = new Scanner(System.in);
while (scanner.hasNext()) {
n = scanner.nextInt();
if(n==0)return;
createGraph();
girl_frined = new int [boy+1];
int sum = 0;
for (int i = 1; i <=girl; i++) {
flag = new boolean [boy+1];
sum += hungray(i);
}
System.out.println(sum);
}
}
private static int hungray(int i) {
for (int j = 1; j <=boy; j++) {
if (graph[i][j]&&!flag[j]) {
flag[j] = true;
if (girl_frined[j]==0||hungray(girl_frined[j])==1) {
girl_frined[j] = i;
return 1;
}
}
}
return 0;
}
private static void createGraph() {
arr = new char [n][n];
for (int i = 0; i < arr.length; i++) {
arr[i] = scanner.next().toCharArray();
}
girl = 0;
boy = 0;
ArrayList<Node> list = new ArrayList<Node>();
for (int i = 0; i < arr.length; i++) {
int star = 0;
int end = 0;
for (int j = 0; j < arr.length; j++) {
if (arr[j][i]=='X') {
if (end-star>0) {
list.add(new Node(star, end-1, i));
star = end = j+1;
}else {
star = end = j+1;
}
}else if (j==n-1) {
list.add(new Node(star, end, i));
}else {
end++;
}
}
}
girl = list.size();
ArrayList<Node> list2 = new ArrayList<Node>();
for (int i = 0; i < arr.length; i++) {
int star = 0;
int end = 0;
for (int j = 0; j < arr.length; j++) {
if (arr[i][j]=='X') {
if (end-star>0) {
list2.add(new Node(star, end-1, i));
star = end = j+1;
}else {
star = end = j+1;
}
}else if (j==n-1) {
list2.add(new Node(star, end, i));
}else {
end++;
}
}
}
boy = list2.size();
graph = new boolean [list.size()+1][list2.size()+1];
for (int i = 0; i < list.size(); i++) {
for (int j = 0; j < list2.size(); j++) {
Node x1 = list.get(i);
Node x2 = list2.get(j);
if (x1.e>=x2.x&&x1.s<=x2.x&&x2.s<=x1.x&&x2.e>=x1.x) {
graph[i+1][j+1] = true;
}
}
}
}
}
class Node {
int s;
int e;
int x;
public Node(int s,int e,int x) {
this.s = s;
this.e = e;
this.x = x;
}
}
import java.util.ArrayList;
import java.util.Scanner;
public class Main {
private static Scanner scanner;
private static int n;
private static char [][] arr;
private static boolean[][] graph;
private static int boy;
private static int girl;
private static int[] girl_frined;
private static boolean[] flag;
public static void main(String[] args) {
scanner = new Scanner(System.in);
while (scanner.hasNext()) {
n = scanner.nextInt();
if(n==0)return;
createGraph();
girl_frined = new int [boy+1];
int sum = 0;
for (int i = 1; i <=girl; i++) {
flag = new boolean [boy+1];
sum += hungray(i);
}
System.out.println(sum);
}
}
private static int hungray(int i) {
for (int j = 1; j <=boy; j++) {
if (graph[i][j]&&!flag[j]) {
flag[j] = true;
if (girl_frined[j]==0||hungray(girl_frined[j])==1) {
girl_frined[j] = i;
return 1;
}
}
}
return 0;
}
private static void createGraph() {
arr = new char [n][n];
for (int i = 0; i < arr.length; i++) {
arr[i] = scanner.next().toCharArray();
}
girl = 0;
boy = 0;
ArrayList<Node> list = new ArrayList<Node>();
for (int i = 0; i < arr.length; i++) {
int star = 0;
int end = 0;
for (int j = 0; j < arr.length; j++) {
if (arr[j][i]=='X') {
if (end-star>0) {
list.add(new Node(star, end-1, i));
star = end = j+1;
}else {
star = end = j+1;
}
}else if (j==n-1) {
list.add(new Node(star, end, i));
}else {
end++;
}
}
}
girl = list.size();
ArrayList<Node> list2 = new ArrayList<Node>();
for (int i = 0; i < arr.length; i++) {
int star = 0;
int end = 0;
for (int j = 0; j < arr.length; j++) {
if (arr[i][j]=='X') {
if (end-star>0) {
list2.add(new Node(star, end-1, i));
star = end = j+1;
}else {
star = end = j+1;
}
}else if (j==n-1) {
list2.add(new Node(star, end, i));
}else {
end++;
}
}
}
boy = list2.size();
graph = new boolean [list.size()+1][list2.size()+1];
for (int i = 0; i < list.size(); i++) {
for (int j = 0; j < list2.size(); j++) {
Node x1 = list.get(i);
Node x2 = list2.get(j);
if (x1.e>=x2.x&&x1.s<=x2.x&&x2.s<=x1.x&&x2.e>=x1.x) {
graph[i+1][j+1] = true;
}
}
}
}
}
class Node {
int s;
int e;
int x;
public Node(int s,int e,int x) {
this.s = s;
this.e = e;
this.x = x;
}
}