package com.raylew.algorithm.poj;
import java.util.LinkedList;
import java.util.Scanner;
/**
* Created by RayLew on 2015/7/10.
* QQ:897929321
* from:poj2965
* algorithm:dfs,enum
*/
/*
Sample Input
- + - -
- - - -
- - - -
- + - -
Sample Output
6
1 1
1 3
1 4
4 1
4 3
4 4
*/
public class POJ2965 {
boolean[] state = new boolean[65536];//状态
int N = 4;
int minimumCount = 0;
public static void main(String[] args) {
int N = 4;
int[][] matrix = new int[N][N];
Scanner scanner = new Scanner(System.in);
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
String str = scanner.next();
if (str.equals("+")) {
matrix[i][j] = 1;
}
}
}
POJ2965 poj2965 = new POJ2965();
poj2965.bfs(matrix);
}
/**
* enum all possible situation
*/
public void bfs(int[][] matrix) {
//init
LinkedList<String> list1 = new LinkedList<String>();
state[convertMatrixToNum(matrix)] = true;
list1.add(convertMatrixToString(matrix));
LinkedList<String> list2 = new LinkedList<String>();
//start bfs
while (true) {
if (list1.size() == 0) {
if (list2.size() == 0) {
System.out.println("Impossible");
break;
}
minimumCount++;
for (String item : list2) {
list1.add(item);
}
list2 = new LinkedList<String>();
}
int[][] first_matrix = convertStringToMatrix(list1.removeFirst());
state[convertMatrixToNum(first_matrix)] = true;
if (isMatched(first_matrix)) {//matched
System.out.println(minimumCount);
//display(first_matrix);
return;
}
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
int[][] new_matrix = flip(first_matrix, i, j);
if (isMatched(new_matrix)) {//matched
System.out.println(minimumCount + 1);
//display(new_matrix);
return;
} else {
//unmatched
int hash = convertMatrixToNum(new_matrix);
if (!state[hash]) {
String matrixStr = convertMatrixToString(new_matrix);
list2.add(matrixStr);
}
}
}
}
}
}
/**
* flip the i row and j column into the opposite
*
* @param matrix
* @param i
* @param j
*/
public int[][] flip(int[][] matrix, int i, int j) {
//flip i row
for (int k = 0; k < N; k++) {
matrix[i][k] = 1 - matrix[i][k];
}
//flip j column
for (int k = 0; k < N; k++) {
matrix[k][j] = 1 - matrix[k][j];
}
return matrix;
}
/**
* judge whether the new matrix is 0
*
* @param matrix
* @return
*/
public boolean isMatched(int[][] matrix) {
int num = 0;
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
num += matrix[i][j];
}
}
//all of them is 0
return (num == 0);
}
/**
* convert matrix to a number(exactly hash value)
*
* @param matrix
* @return
*/
public int convertMatrixToNum(int[][] matrix) {
int num = 0;
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
int radix = N * N - 1 - (i * N + j);
num += matrix[i][j] * Math.pow(2, radix);
}
}
return num;
}
/**
* convert matrix to string
*
* @param matrix
* @return
*/
public String convertMatrixToString(int[][] matrix) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
sb.append(matrix[i][j]);
}
}
return sb.toString();
}
/**
* convert string to matrix
*
* @param str
* @return
*/
public int[][] convertStringToMatrix(String str) {
int[][] matrix = new int[N][N];
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
int index = i * N + j;
matrix[i][j] = Integer.parseInt(str.charAt(index) + "");
}
}
return matrix;
}
/**
* print matrix to console
*
* @param matrix
*/
public void display(int[][] matrix) {
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
System.out.print(matrix[i][j] + " ");
}
System.out.println();
}
System.out.println();
}
}