POJ1321 棋盘摆放问题(DFS)

每日打卡(1/2)  

传送连接:点击打开链接

题目大意:

    给你一个n*n的棋盘,其中只有标#的格子能放棋子,且两个棋子不能位于棋盘的同一行或同一列,要求摆k个棋子,求方案数。

大致思路:

    裸DFS,和n皇后思路相同。以行数作为基准,如果当前列有符合要求的格子,可以采取放或不放两种方法,最后求和。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<cstdlib>
#include<algorithm>
using namespace std;
const int maxn = 10;

int n,k,a[maxn][maxn];
long long ans;
bool vis[maxn];

void dfs(int x,int tot)
{
	if(tot<k&&x>=n) return;
	if(tot==k) {
		ans++;
		return;
	}
	else {
		for(int i=0;i<n;i++)
		{
			if(a[x][i]&&!vis[i]) {
				vis[i] = 1;
//				cout<<i<<endl;
				dfs(x+1,tot+1);
				vis[i] = 0;
			}
		}
		dfs(x+1,tot);
	}
}
int main()
{
	while(scanf("%d%d",&n,&k)!=EOF&&n!=-1&&k!=-1)
	{
		char s;
		ans = 0;
		memset(a,0,sizeof(a));
		memset(vis,0,sizeof(vis));
		for(int i=0;i<n;i++)
		 for(int j=0;j<n;j++)
		 {
		 	cin>>s;
		 	if(s=='#') a[i][j] = 1;
		 	else a[i][j] = 0;
		 }
		dfs(0,0);
		cout<<ans<<endl; 
	}
	return 0;
}

这个解法会TLE,这时候我们可以考虑剪枝。

不难想到,如果总共有5行,当前已经搜到了第4行,却还有3个棋子没有摆,那么这种情况就可以剪枝掉。

因此,我们在dfs的开头加上一行:

if(k-tot>n-x) return;

如果剩下的棋子超过剩下的行数,那么就剪枝掉。

所以就AC了。

                                                                                                                  

    原文作者:骑士周游问题
    原文地址: https://blog.csdn.net/zxwsbg/article/details/79346610
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞