poj1321_dfs_棋盘问题
最近一直在写搜索的题,一直不理想,我觉得原因是:
1.对题意理解不到位,有时候往往曲解题意,导致费事费时。
2.自己想问题不透彻,不能一步到位,每次写完代码都有bug,各种改,各种不对。
3.还是对递归理解的很别扭啊,网上说:写递归要始终把握住两点:1、进入下一级递归的条件;2、递归结束条件。
摘了网上的一段话:
“递归的主要问题应该是思维的跨度,初学递归时总是喜欢去想细节,甚至脑子里一步一步的跟踪,这对于初学时是不应该的,很多初学者在不相信思维跨度时,也就不相信递归求解是正确的。
我感觉学递归最大的问题是信任思维的跨度,直接将前n-1前移了,再去移第n个,一下子移n-1个,我感觉就相当于移1个,只是一种跨度而已。”
希望自己能有所感悟。
下面说一下这个棋盘的问题,
题意:有一个矩阵棋盘,棋盘中#可以放棋子,.不可以放。求给定的n*n的棋盘,往里放k个棋子的方案个数。
分析:dfs求所有的情况。从i=1 to i=n-k+1遍历,其中当i=1时,从2到n行有Cn-i,k-1种选择。
代码:
View Code
1 #include <iostream> 2 #include <stdio.h> 3 #include <memory.h> 4 #include <memory.h> 5 #include <stdio.h> 6 #include <time.h> 7 using namespace std; 8 9 const int maxnum=9; 10 char array[maxnum][maxnum]; 11 bool row[maxnum]; 12 bool col[maxnum]; 13 int cnt; 14 int n,k; 15 16 bool judge(int i,int j) 17 { 18 if(!col[j] && !row[i] && array[i][j]=='#') 19 return true; 20 return false; 21 } 22 23 void dfs(int currow,int num) 24 { 25 if(num==k) 26 { 27 cnt++; 28 return ; 29 } 30 int i,j; 31 for(i=currow;i<=n;i++) 32 { 33 for(j=1;j<=n;j++) 34 { 35 if(judge(i,j)) 36 { 37 row[i]=true; 38 col[j]=true; 39 dfs(i+1,num+1); 40 row[i]=false; 41 col[j]=false; 42 } 43 } 44 } 45 } 46 47 int main() 48 { 49 int i,j; 50 while(scanf("%d%d",&n,&k)!=EOF) 51 { 52 if(n==-1 && k==-1) 53 break; 54 getchar(); 55 for(i=1;i<=n;i++) 56 { 57 for(j=1;j<=n;j++) 58 scanf("%c",&array[i][j]); 59 if(j==n+1) getchar(); 60 } 61 62 cnt=0; 63 memset(row,false,sizeof(row)); 64 memset(col,false,sizeof(col)); 65 for(i=1;i<=n-k+1;i++) //首行的开始位置 66 { 67 for(j=1;j<=n;j++) 68 { 69 if(judge(i,j)) 70 { 71 row[i]=true; 72 col[j]=true; 73 dfs(i+1,1); 74 row[i]=false; 75 col[j]=false; 76 } 77 } 78 } 79 printf("%d\n",cnt); 80 } 81 return 0; 82 }