// 376K 16MS G++ #include <stdio.h> #include <string.h> #define MAX 10 char occupiedColumn[MAX]; char occupiedRow[MAX]; char board[MAX][MAX]; int W; int H; int chessNum; #define INF 99999 int dfs(int rowId, int unDeployedChessNum) { int combinationNum = 0; if (unDeployedChessNum == 0) { // no chess to deploy, a valid try. return 1; } // if has enterted the last row, but still have > 1 chess to deploy if (rowId == H-1) { if (unDeployedChessNum > 1) { return 0; // this case is invalid, return 0; } } // if all row has been checked, but still left chess, invalid case. if (rowId == H) { if (unDeployedChessNum > 0) { return 0; } } for (int i = 0; i < W; i++) { // check if there are invalid pos on this row. // if this pos is #, and the colomun is not occupied yet. if (board[rowId][i] == '#' && !occupiedColumn[i]) { occupiedRow[rowId] = 1; // this row is occupied occupiedColumn[i] = 1; // this coloumn is coccupied combinationNum += dfs(rowId + 1, unDeployedChessNum - 1); occupiedRow[rowId] = 0; occupiedColumn[i] = 0; } } // also try no deploy chess on this row. combinationNum += dfs(rowId + 1, unDeployedChessNum); return combinationNum; } void solve() { int combinationNum = dfs(0, chessNum); printf("%d\n", combinationNum); } int main() { while(1) { scanf("%d %d", &W, &chessNum); if (W == -1 && chessNum == -1) { return 0; } memset(occupiedColumn, 0, sizeof(occupiedColumn)); memset(occupiedRow, 0, sizeof(occupiedRow)); H = W; for (int i = 0; i < H; i++) { scanf("%s", board[i]); } solve(); } }
八皇后的简单变种,正方形棋盘的某些区域不能再放棋子,其他的都一模一样,
离上一次写八皇后过去好久了,果然有些生疏了,不过也基本顺利写出来了:
首先要搞一个标记某列是否已经有棋子的flag数组C(不需要行数组的的flag,因为在dfs时是顺序处理行的,不用考虑行占用的情况),
然后就是dfs内部在遍历某一行有哪些位置可以放置棋子时,既要保证此列没有被占用,也要考虑是否是'#', 如果都满足,就将此列标记为被占用,
然后dfs下一行,同时要放置的棋子数量也-1,
除了选择本行放置棋子外,也可以考虑不放置,直接奔下一行dfs,只不过要放置的棋子的数量不-1,
最后,如果某一次dfs发现要放置的棋子的数量已经是0,那么这就是一个有效的方法,返回1,代表一种有效的放法。
如果已经到了第H+1行(及所有的行已经都处理过了),仍然有没有放置的棋子,那么这必然是一个无效的放法,返回0.
还可以有些优化,比如,还剩下K行可以放,但是还有 >K 的棋子没放,那么可以直接返回0了。
在每次DFS中,维护一个在此DFS节点中有效方法的总和,累加每次子DFS的返回值。
这种题一般会有更复杂的变种,如果将棋子编号,或者换成不同颜色的棋子,这种情况下组合数量会更多(虽然布局一样,但是颜色编号分布不一样),
不过却很简单,只需在上面题的基础上直接 乘以 棋子数量N的排列数 N!即可(布局定了,颜色如何怕不其实就是内部的排列组合了).