POJ 1321 搜索题DFS
题目大意:在棋盘中是“#”号的地方放置k个棋子,要求没有棋子在同一行同一列。求有多少种不同的放法。
这道题有点很像 N后问题。。不过比N后问题要简单一些。
这里我想说两种思路:
1.因为每一行有且只有一个棋子,所以从第一行DFS到最后一行就能得到所有的解。
2.由于这道题目中的棋盘边长n不大,所以也可以用是“#”号坐标来进行DFS。首先把所有是“#”号的左边都记录下来,然后在从中抽取k个不是在同一行同一列的点。
方法一code:
#include <stdio.h> #include <stdlib.h> #include <string.h> char maze[10][10]; int f[10]; int n,k; int res; void DFS(int r,int t) { if(t==k) { res++; return; } if(r>=n) return; for(int i=0;i<n;i++) { if(!f[i]&&maze[r][i]=='#') { f[i]=1; DFS(r+1,t+1); f[i]=0; } } DFS(r+1,t); } int main() { while(scanf("%d%d",&n,&k)!=EOF&&(k+n)>0) { getchar(); res=0; memset(f,0,sizeof(f)); for(int i=0;i<n;i++) scanf("%s",maze[i]); DFS(0,0); printf("%d\n",res); } return 0; }
方法2code:
#include <iostream> #include <cstdio> #include <cstdlib> #include <cstring> #include <vector> using namespace std; char maze[10][10]; struct node { int x,y; node(int a,int b) :x(a),y(b) {} }; vector<node> q,tmp; //tmp为已经加入解集的点集 q为所有为‘#’的点集 int N,k; int res; int check(int t) //检查第t个点是否满足要求,满足的话就可以把它加入 { for(int i=0;i<tmp.size();i++) { if(tmp[i].x==q[t].x || tmp[i].y==q[t].y) return 0; } return 1; } void DFS(int t,int m) //t表示tmp中已有元素的个数。m表示开始检索的坐标点的前一个点 { if(t>k) { res++; return; } for(int i=m+1;i<q.size();i++) { if(check(i)) { tmp.push_back(q[i]); DFS(t+1,i); tmp.pop_back(); //类似于回朔 } } } int main(void) { char ch; while(scanf("%d%d",&N,&k)!=EOF&&(N+k)>=0) { getchar(); q.clear(); tmp.clear(); res=0; for(int i=0;i<N;i++) { for(int j=0;j<N;j++) { scanf("%c",&ch); if(ch=='#') { q.push_back(node(i,j)); } } getchar(); } DFS(1,-1); cout<<res<<endl; } }