非常简单的一道DFS题,用常规回溯就可以直接做出来,我十分钟就写好了代码可是昨天总是无法AC,今天搜了半天题解看到这句话我才意识到代码中存在的问题:
这道题目类似N皇后问题,与之不同的是每一行不一定有棋盘,所以dfs里要注意不一定是当前行。
之前总是改来改去混乱找不到头绪,一瞬间醍醐灌顶。之后64MS 过的。
#include<stdio.h>
#include<string.h>
char pan_one[10][10];
int vis[10];
int n, k, num;
void dfs( int row, int step);
int main(void){
int i, j;
while( scanf("%d%d", &n, &k) != EOF){
getchar();
if( n == -1 & k == -1) break;
memset( vis, 0, sizeof(vis));
for( i = 0; i < n; i++){
gets(pan_one[i]);
}
num = 0;
dfs( 0, 0);
printf("%d\n",num);
}
return 0;
}
void dfs( int row, int step){
int i, j;
if( step == k){
num++; return;
}
else if( row >= n) return;
for( i = row; i < n; i++){
for( j = 0; j < n; j++){
if( pan_one[i][j] == '#' && !vis[j]){ // 和已有的棋子不同位置
vis[j] = 1;
dfs( i+1, step+1);
vis[j] = 0;
}
}
}
return;
}
之后查看了一下剪枝的代码,压到了16MS
#include<stdio.h>
#include<string.h>
char pan_one[10][10];
int vis[10];
int n, k, num;
void dfs( int row, int step);
int main(void){
int i, j;
while( scanf("%d%d", &n, &k) != EOF, n != -1 && k != -1){
getchar();
memset( vis, 0, sizeof(vis));
for( i = 0; i < n; i++) gets(pan_one[i]);
num = 0;
dfs( 0, 0);
printf("%d\n",num);
}
return 0;
}
void dfs( int row, int step){
int i, j;
if( step == k){ num++; return;}
else if( row >= n) return;
else if( n - row + step < k) return; // 如果剩下的行数小于将放的棋子数,则剪枝
for( i = row; i < n; i++)
for( j = 0; j < n; j++)
if( pan_one[i][j] == '#' && !vis[j]){ // 和已有的棋子不同位置
vis[j] = 1;
dfs( i+1, step+1);
vis[j] = 0;
}
return;
}