A - 棋盘问题 POJ - 1321
dfs 复杂度计算: dfs共进行a步,每步需要循环n次,复杂度为 a^n次方
首先是暴力 an*n,果然炸了
#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
char mp[10][10];
int rank[10], col[10];
int ans, n;
void dfs(int s, int k) { // 每次记录某一列是不是存在了, dfs进入下一行
if(k == 0) {
ans ++;
// cout << "***ans = " << ans << endl;
return ;
}
for(int i = s; i < n; i++) {
for(int j = 0; j < n; j++) {
if(!col[j] && !rank[i] && mp[i][j] == '#'){
rank[i] = 1;
col[j] = 1;
dfs(s+1, k-1);
rank[i] = 0;
col[j] = 0;
}
}
}
}
void init() {
ans = 0;
memset(rank, 0, sizeof(rank));
memset(col, 0, sizeof(col));
}
int main() {
// freopen("test.in", "r", stdin);
int k;
while(~scanf("%d%d", &n, &k)) {
if(n == -1 && k == -1) break;
for(int i = 0; i < n; i++) {
scanf("%s", mp[i]);
}
init();
dfs(0, k);
printf("%d\n", ans);
}
return 0;
}
剪枝,每次从上次搜索过得那行之后搜索,记录进入了哪几列,每次行的遍历不用全部进行,例如
要放9枚棋子,棋盘规格为10,则从0开始,在0~1之间一定存在一个满足条件得位置,否则往后也不可能成立
条件中k <= n <= 8此时最坏情况为走8步,每步循环8次,即 88 = 224 < 1e7
AC代码
#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
char mp[10][10];
int col[10];
int ans, n;
void dfs(int s, int k) { // 每次记录某一列是不是存在了, dfs进入下一行
if(k == 0) {
ans ++;
return ;
}
for(int i = s; i <= n-k; i++) { // Eg:要放9枚棋子,棋盘规格为10,则从0开始,在0~1之间一定存在一个满足条件得位置(可能不在本行),否则条件不成立
for(int j = 0; j < n; j++) {
if(!col[j] && mp[i][j] == '#') {
col[j] = 1;
dfs(i+1, k-1);
col[j] = 0;
}
}
}
}
void init() {
ans = 0;
memset(col, 0, sizeof(col));
}
int main() {
// freopen("test.in", "r", stdin);
int k;
while(~scanf("%d%d", &n, &k)) {
if(n == -1 && k == -1) break;
for(int i = 0; i < n; i++) {
scanf("%s", mp[i]);
}
init();
dfs(0, k);
printf("%d\n", ans);
}
return 0;
}