您的位置:首页 > 其它

POJ-1321-棋盘问题

2016-03-09 13:30 239 查看
K - 棋盘问题

Time Limit:1000MS Memory Limit:10000KB 64bit IO Format:%I64d & %I64u

Submit

Status

Practice

POJ 1321

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

…#

..#.

.#..

#…

-1 -1

Sample Output

2

1

深度搜索,递归解决

递归终止条件:棋子已下完,搜索越界,当前搜索坐标已被访问过。

满足以上任意条件就可以结束当前结点.

搜索时可能出现,棋子下完,棋盘仍然有剩余的情况,此时要接着下一行继续搜索,这样才会得出最多种方法

还有递归的时候,千万别一层层的想那么深,那只会让人抓狂,毕竟人脑不是CPU。

实现递归时,人脑的思维只需要着重实现一层,再往下交给计算机就行。

代码

#include<stdio.h>
#include<string.h>
#include<string>
#include<stack>
#include<queue>
#include<math.h>
#include<limits.h>
//#include<malloc.h>//加上这个头文件会编译错误,原因不明
#include<iostream>
#include<algorithm>
using namespace std;
char map[10][10];//接收地图
int visited[10];//当前列已访问标记为0,未访问标记为1
int sum;//记录方法总数
int n;//地图大小
int k;//棋子数量
void DFS(int line,int num)//传入当前行和已用棋子数
{
if(num==k)//如果棋子用完
{
sum++;//方法总数加一
return;//结束当前递归
}
if(line>=n)//如果搜索越界
return;//结束搜索
for(int i=0;i<n;i++)//棋子没用完,搜索没越界,那就继续搜索
{
if(visited[i]==1&&map[line][i]=='#')//坐标可被访问且未被访问过
{
visited[i]=0;//先标记当前坐标为已访问,因为后面还要递归搜索
DFS(line+1,num+1);//行数加一,已用棋子数加一,继续搜索
visited[i]=1;//完成一遍后,vsited全部标记为未访问,准备为寻找下一种方法继续标记
}
}
DFS(line+1,num);//如果未搜索完一遍,棋子就用完了,那就接着下一行搜索新的方式,防止遗漏
return;
}
int main()
{
while(~scanf("%d%d",&n,&k))
{
if(n==-1&&k==-1)
break;
for(int i=0;i<n;i++)
{
for(int j=0;j<n;j++)
{
cin>>map[i][j];//之前用scanf接收,结果异常,改成cin就没事了,未解之谜。。。。
}
}
sum=0;//初始化方法总数
for(int i=0;i<10;i++)//当前列未访问标记为1
visited[i]=1;
//memset(visited,1,sizeof(visited));//这种初始化方式好像不对,把它注释掉了
DFS(0,0);//从第0行开始搜索,已用棋子数为0
printf("%d\n",sum);
}
return 0;
}


搜索问题确实有一定的套路可循
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: