poj1321

这道题目是典型的深搜题,以前做过的题目是给定一个矩阵棋盘,要求每一行每一列只能安排一个棋子,且安排的棋子数即为行数,这题要相对复杂一些,有如下不同点:

1)棋盘是嵌在矩阵中的,不是单纯的矩阵

2)要求安排的棋子数<=矩阵的行数

主要的难点在于第二个不同点。要枚举所有的可能还是比较费时的,所以要用到剪枝。

那么主要思路就是利用深搜枚举所有可能情况,枚举的关键是后续棋子放置的行号要小于当前已经安排棋子的行号,这样才不会造成重复枚举。同时要注意回溯和剪枝。

回溯的关键就是将已经安排棋子的列号枚举完后,设置该列号为可放置。

剪枝的关键在于:当前可放棋子的行数要大于或等于要放置的棋子数-已经放置的棋子数,这里假设每行至少可以放置一个棋子(实际上有可能不能实现)

下面的题目实际上是该题的一种特殊情况:

给定一个矩阵棋盘n*m,和要放置的棋子数k(k<=n),要求每一行每一列只能放置一个棋子,问有多少种放置方案。

下面是代码:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define Max 10
bool flag[Max][Max];
bool vi[Max];
int n,k;
__int64 count;
void dfs(int level,int num){
	if(num==k){
		count++;
		return ;
	}
    for(int i=level-1;i>=k-num;i--)
		for(int j=1;j<=n;j++)
			if(flag[i][j] && !vi[j]){
				vi[j]=1;
				dfs(i,num+1);
				vi[j]=0;
			}
}				
int main(){
	while(scanf("%d%d",&n,&k),n!=-1){
		char str;
		memset(flag,0,sizeof(flag));
		memset(vi,0,sizeof(vi));
		for(int i=1;i<=n;i++){
			getchar();
			for(int j=1;j<=n;j++){
				str=getchar();
				if(str=='#')
					flag[i][j]=1;
			}
		}
		count=0;
		dfs(n+1,0);
		printf("%I64d\n",count);
	}
	return 0;
}
				


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值