poj1321-棋盘问题

在一个给定形状的棋盘(形状可能是不规则的)上面摆放棋子,棋子没有区别。要求摆放时任意的两个棋子不能放在棋盘中的同一行或者同一列,请编程求解对于给定形状和大小的棋盘,摆放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

题意:给一个n*n的矩阵,(n<=8) '#'表示可走,'.'表示不通行,再给出k个完全相同的棋子,(k<=n)棋子不能同行同列,问有几种走法

 

解析:这个题思路很好想,用col[ ]数组做列的标记,如col[y]==1表示第i列不能走,对于每一行的'#'位置,棋子有走和不走两种可能性。以此进行深搜。

不过我在代码书写上犯了错误,下面附上错误代码:

#include<bits/stdc++.h>
using namespace std;
int N,K;
char c[10][10];
bool col[10];//列是否被访问 
int cnt=0;
void dfs(int x,int k){//x行有放棋子和不放棋子两种情况‘ 
	if(k>=K){
		cnt++;
		return;
	}
	if(x>N+1)return; 
	for(int y=1;y<=N;y++){
		if(c[x][y]=='#'&&!col[y]){
			col[y]=1;
			dfs(x+1,k+1); 
			col[y]=0;
		}
	}
	return;
}
int main()
{
	while(cin>>N>>K){
		if(N==-1&&K==-1)break;
		memset(c,0,sizeof(c));
		for(int i=1;i<=N;i++){
			for(int j=1;j<=N;j++){
				cin>>c[i][j];
			}
		}
		memset(col,0,sizeof(col));
		cnt=0;
		for(int i=1;i<=N;i++)
			dfs(i,0);
		cout<<cnt<<endl;
	}
	return 0;
}

请看主函数中的这条语句:

for(int i=1;i<=N;i++)
	dfs(i,0);

我想从外部按行数遍历,但是这么遍历的意思是棋子每到'#'处都走,及选择“不走”的情况就被忽略掉了,然后我就陷入了2小时找bug阶段。。。

正确代码如下:

#include<string.h>
#include<iostream>
using namespace std;
int N,K;
char c[10][10];
bool col[10];//列是否被访问 
int cnt=0;
void dfs(int x,int k){//x行有放棋子和不放棋子两种情况‘ 
	if(k>=K){
		cnt++;
		return;
	}
	if(x>N+1)return; 
	dfs(x+1,k);//不放 
	for(int y=1;y<=N;y++){
		if(c[x][y]=='#'&&!col[y]){
			col[y]=1;
			dfs(x+1,k+1);//放 
			col[y]=0;
		}
	}
	return;
}
int main()
{
	while(cin>>N>>K){
		if(N==-1&&K==-1)break;
		memset(c,0,sizeof(c));
		for(int i=1;i<=N;i++){
			for(int j=1;j<=N;j++){
				cin>>c[i][j];
			}
		}
		memset(col,0,sizeof(col));
		cnt=0;
		dfs(1,0);
		cout<<cnt<<endl;
	}
	return 0;
}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值