https://vjudge.net/contest/65959#problem
A题POJ1321
题目类型:DFS类型题目
难易程度:1
被吊打的老年选手,现在连字符串图的读入都有点问题了。不过多写几下就好了。
思路:
DFS的参数是 当前遍历到的层数 和 当前放置的棋子的个数。
用一个标记数组来标记当前列有没有被访问过。
DFS具体过程,对当前行的每一列进行判断(看当前位置是否是棋盘,当前位置是否被标记过),如果是棋盘,且没有被标记过,那么就将当前列标记,并进入下一行进行DFS(row+1,num+1)。(DFS前后要对放置棋子的个数进行标记和取消标记)。
当对整行都遍历了之后,再 DFS(row+1,num),跨过当前行用下一行。
DFS的出口是:当num == k(即放置的棋子数到达要求的棋子数时,停止。还有就是当访问的行row 越界后,也停止)
#include <iostream> #include <cstdio> #include <cstdlib> #include <cstring> using namespace std; char c; int n, k; int vis_col[10]; int g[10][10]; int ans = 0; void DFS(int row, int num) { if(num == k) { ans ++; return; } if (row >= n) return; for(int icol = 0; icol < n; ++icol) { if(g[row][icol] && !vis_col[icol]) { vis_col[icol] = 1; DFS(row+1, num+1); vis_col[icol] = 0; } } DFS(row+1, num); } int main() { //freopen("in.txt", "r", stdin); //freopen("out.txt", "w", stdout); while(scanf("%d %d", &n, &k) != EOF && n!=-1 && k!=-1) { memset(g, 0, sizeof(g)); ans = 0; memset(vis_col, 0, sizeof(vis_col)); for(int i = 0; i < n; ++i) { for(int j = 0; j < n; ++j) { cin >> c; if(c == '#') g[i][j] = 1; } } DFS(0,0); printf("%d ", ans); } return 0; }