要求:在一个给定形状的棋盘(形状可能是不规则的)上面摆放棋子,棋子没有区别。要求摆放时任意的两个棋子不能放在棋盘中的同一行或者同一列,请编程求解对于给定形状和大小的棋盘,摆放k个棋子的所有可行的摆放方案C。
方法:回溯法
1.深搜函数的参数为行数。
2.used[i]=1表示第i列已摆棋子,这样可以减少搜索一列是否会冲突。
3.一行放一个,然后搜索下一行,这样可以减少搜索一行是否会冲突。
4.记得放一个棋子,记录个数。
#include<iostream>
#include<stdio.h>
#include<string.h>
#include<algorithm>
#define inf 0x3f3f3f3f
using namespace std;
int n , k ;
int num ;
int cnt ;
char map1[10][10] ;
int used[10] ;//标记一列是否用过
bool canplace(int x ,int y)
{
int i , j ;
int flag = 1 ;
for(i = 0 ; i < x ; i ++)
if(map1[i][y] == '*')
flag = 0 ;
for(i = 0 ; i < y ; i ++)
if(map1[x][i] == '*')
flag = 0 ;
return flag ;
}
void dfs(int row)
{
int i , j ;
if(num == k)
{
cnt ++ ;
return ;
}
if(row == n)
return ;
for(i = 0 ; i < n ; i ++)//一行放一个
{
if(used[i] == 0 && map1[row][i] == '#')
{
used[i] = 1 ;
num ++ ;
dfs(row + 1) ;
used[i] = 0 ;
num -- ;
}
}
dfs(row + 1) ;//有时候上面的for循环会一个都放不了导致无法到达下一层
}
int main()
{
int i , j ;
char s[10] ;
while(scanf("%d%d" , &n , &k) && !(n == -1 && k == -1))
{
for(i = 0 ; i < n ; i ++)
{
scanf("%s" , &s) ;
for(j = 0 ; j < n ; j ++)
map1[i][j] = s[j] ;
}
num = 0 ;
cnt = 0 ;
memset(used , 0 , sizeof(used)) ;
dfs(0) ;
printf("%d\n" , cnt) ;
}
}