Description
在一个给定形状的棋盘(形状可能是不规则的)上面摆放棋子,棋子没有区别。要求摆放时任意的两个棋子不能放在棋盘中的同一行或者同一列,请编程求解对于给定形状和大小的棋盘,摆放k个棋子的所有可行的摆放方案C。
Input
输入含有多组测试数据。
每组数据的第一行是两个正整数,n k,用一个空格隔开,表示了将在一个n*n的矩阵内描述棋盘,以及摆放棋子的数目。 n <= 8 , k <= n
当为-1 -1时表示输入结束。
随后的n行描述了棋盘的形状:每行有n个字符,其中 # 表示棋盘区域, . 表示空白区域(数据保证不出现多余的空白行或者空白列)。
每组数据的第一行是两个正整数,n k,用一个空格隔开,表示了将在一个n*n的矩阵内描述棋盘,以及摆放棋子的数目。 n <= 8 , k <= n
当为-1 -1时表示输入结束。
随后的n行描述了棋盘的形状:每行有n个字符,其中 # 表示棋盘区域, . 表示空白区域(数据保证不出现多余的空白行或者空白列)。
Output
对于每一组数据,给出一行输出,输出摆放的方案数目C (数据保证C<2^31)。
Sample Input
2 1 #. .# 4 4 ...# ..#. .#.. #... -1 -1
Sample Output
2 1
分析:回溯法,这题要求的是方案数量。刚开始的时候就是用二维数组暴搜,但是就是不知道怎么判断这个解是不是重复的,因为棋子没有区别,所以4个位置放4个棋子有24种方法,但是如果棋子相同的话就是一种了。想想每次排序再存起来判断的话会超时,所以就采取了按行(以按行为例)或按列搜索的方法来解。从第一行开始搜索,如果这一行中有满足条件的位置就再搜索下一行,如果这一行没有的话就搜索下下行。再加个判断条件,如果超过N的话就结束,这样到了最后一行,有结果就加一,没有就回溯。有了按按搜索这样一个顺序,再加上判断条件,就不会出现重复的排列了。
import java.util.Scanner; public class Main { static int N, M; static boolean[][] path; static boolean[] xP; static boolean[] yP; static int ans; static void DFS(int row, int n) { if (n == M) { ans++; return; } if (row > N) //配合下面DFS(row+1,num); 语句使用,避免搜索越界 return; for (int j = 1; j <= N; j++) { if (path[row][j] && !yP[j] && !xP[row]) { yP[j] = true; xP[row] = true; DFS(row + 1, n + 1); yP[j] = false; xP[row] = false; } } DFS(row + 1, n);// 如果该行没有合适的位置,搜索下一行。 } public static void main(String[] args) { Scanner sc = new Scanner(System.in); while (true) { N = sc.nextInt(); M = sc.nextInt(); if (N == -1) { break; } String in[] = new String[N + 1]; path = new boolean[10][10]; xP = new boolean[10]; yP = new boolean[10]; ans = 0; for (int i = 1; i <= N; i++) { in[i] = sc.next(); for (int j = 1; j <= N; j++) { if (in[i].charAt(j - 1) == '#') { path[i][j] = true; } } } DFS(0, 0); System.out.println(ans); } } }
版权声明:本文为博主原创文章,未经博主允许不得转载。