棋盘问题
Description
在一个给定形状的棋盘(形状可能是不规则的)上面摆放棋子,棋子没有区别。要求摆放时任意的两个棋子不能放在棋盘中的同一行或者同一列,请编程求解对于给定形状和
大小的棋盘,摆放k个棋子的所有可行的摆放方案C。
Input
输入含有多组测试数据。
每组数据的第一行是两个正整数,n k,用一个空格隔开,表示了将在一个n*n的矩阵内描述棋盘,以及摆放棋子的数目。 n <= 8, k <= n
当为 - 1 - 1时表示输入结束。
随后的n行描述了棋盘的形状:每行有n个字符,其中 # 表示棋盘区域,.表示空白区域(数据保证不出现多余的空白行或者空白列)。
Output
对于每一组数据,给出一行输出,输出摆放的方案数目C (数据保证C<2 ^ 31)。
Sample Input
2 1
#.
.#
4 4
...#
..#.
.#..
#...
Sample Output
2
1
#include<stdio.h> #include<iostream> #include <string.h> int chess[9][9]; int vist_col[9]; //列标记 int status; //方案计数器 int n, k; void DFS(int row, int num) //逐行搜索,row为当前搜索行,num为已填充的棋子数 { int j; if (num == k)//棋子用完,搜索结束 { status++; return; } if (row>n) //如果当前行的位置超过棋盘,搜索结束。配合下面DFS(row+1,num); 语句使用,避免搜索越界 return; for (j = 0; j<n; j++)//j为列下标 if (chess[row][j] && !vist_col[j])//如果这个位置可以放棋子,并且棋子还没有放完 { vist_col[j] = 1; //放置棋子的列标记 DFS(row + 1, num + 1); vist_col[j] = 0; //回溯后,说明摆好棋子的状态已记录,当前的列标记还原 } DFS(row + 1, num); //这里是难点,当k<n时,row在等于n之前就可能已经把全部棋子放好 //又由于当全部棋子都放好后的某个棋盘状态已经在前面循环时记录了 //因此为了处理多余行,令当前位置先不放棋子,搜索在下一行放棋子的情况 return; } int main(int i, int j) { while (scanf("%d%d", &n, &k) != EOF) { getchar(); if (n == -1 && k == -1) break; memset(chess, 0, sizeof(chess));//对数组清零操作 memset(vist_col, 0, sizeof(vist_col)); status = 0; for (i = 0; i<n; i++) { for (j = 0; j<n; j++) { char temp; scanf("%c", &temp); if (temp == '#') { chess[i][j] = 1; } } getchar(); } DFS(0, 0); //注意初始化的值别弄错了 printf("%d\n", status); } return 0; }
等风起的那一天,我已准备好一切