Don't Get Rooked |
题目的内容只是在四皇后的基础之上加上了点障碍,处理的方式还是一样,如果是四皇后的问题的话,那么可以一行一行的放置,现在的问题可以一行放两个(在中间被墙阻挡的时候)这时就要将一行分开遍历,将墙的两边看做是不同的行处理
题目链接:
http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=108&page=show_problem&problem=580
1 #include<stdio.h> 2 #include<string.h> 3 #define MAXN 6 4 int maze[MAXN][MAXN], visit[MAXN][MAXN]; 5 int max; 6 7 int checkcolumn(int x, int y, int n) 8 {//只是判断上方是不是墙壁或者已放有车 9 int i, j, up; 10 for(i=x; i>=0 && maze[i][y] != MAXN && maze[i][y] != 1; --i); 11 if(i<0 || maze[i][y] == MAXN) return 1; 12 else return 0; 13 } 14 15 int Traverse(int x, int y, int cnt, int n) 16 { 17 int i, j, left, right, flag = 0, t; 18 if(x == n) 19 {//x == n是表示整个遍历完成 20 if(max < cnt) max = cnt; 21 return 0; 22 } 23 for(t=y; t<n && maze[x][t] == MAXN; ++t); //除去一开始的连续墙壁 24 if(t >=n ) Traverse(x+1, 0, cnt, n); //如果一行都是墙壁,那下面就没戏了,但生活还是需要继续的,对吗?所以继续遍历下一行 25 for(left=t; left<n && maze[x][left] != MAXN; ++left) 26 ; //找到这一行中可行的列,遇到墙壁结束,主要是为了分割出一行中的子行 27 flag = left >= n ? 0 : 1; //判断这行遍历后是否需要转为下一行,即能够判断出右边还有没子行(一行中墙壁后面的墙) 28 for(j=t; j<left; ++j) 29 { 30 if(checkcolumn(x, j, n)) 31 { 32 maze[x][j] = 1; 33 if(!flag)Traverse(x+1, 0, cnt+1, n); 34 else Traverse(x, left, cnt+1, n); 35 maze[x][j] = 0; 36 } 37 else 38 {//如果不允许添加车,那么就继续遍历咯,cnt的值不变而已 39 if(!flag)Traverse(x+1, 0, cnt, n); 40 else Traverse(x, left, cnt, n); 41 } 42 } 43 return 0; 44 } 45 46 int main() 47 { 49 int i, j, n, x, y, temp, r, c, cnt; 50 char input; 51 while(scanf("%d", &n) != EOF && n) 52 { 53 getchar(); 54 max = flag = 0; 55 memset(maze, 0, sizeof(maze)); 56 for(i=0; i<n; ++i) 57 { 58 for(j=0; j<n; ++j) 59 { 60 scanf("%c", &input); 61 if(input == 'X') maze[i][j] = MAXN;
67 } 68 getchar(); 69 } 70 cnt = 0; 71 Traverse(0, 0, cnt, n); 72 printf("%d\n", max); 74 } 75 return 0; 76 }