Chinaunix首页 | 论坛 | 博客
  • 博客访问: 417510
  • 博文数量: 66
  • 博客积分: 1416
  • 博客等级: 上尉
  • 技术积分: 922
  • 用 户 组: 普通用户
  • 注册时间: 2006-09-16 10:37
个人简介

高級Oracle DBA,善長Linux系統維運以及Oracle數據庫管理,開發,調優. 具有多年PL/SQL開發經驗.

文章分类

全部博文(66)

文章存档

2015年(9)

2014年(4)

2013年(5)

2010年(1)

2009年(3)

2008年(6)

2007年(30)

2006年(8)

我的朋友

分类: C/C++

2007-12-13 13:42:21

八皇後問題是一個比較有意思的問題.
在一個8x8的棋盤上,如何擺放8個祺子才能使皇後無法相互攻擊.
每一行,每一列,每一條斜線都只能有一個皇後.
列出所有的擺法

有一個比較簡單的方法是
將每一個皇後編上號1,2,3,4,5,6,7,8, 然後列出這8個數的全排列,
可以得到每行,每列都只有一個後的擺法,再替除斜率等於1的輸出.
如何輸出全排列,有好幾種算法, 可以用google搜索找到答案

char  data[8]  ;
data[n]    存放第n個棋子擺放在第一排的位置 .  n< 8,  data[n] <8

檢查是否同一斜線

int king_valid(char *str)
{
        int i,j;
        int loop;
        for(i=1; i<8; i++) {
                 loop=8-i;
                 for(j=0; j<loop; j++) {
                         if (abs(str[j]-str[j+i]) == i) {
                                 return 0;
                         }
                 }
        }
        return 1;
}


當然這樣做的效率不怎麼高.

解法二:回溯法
用回溯法處理要快一點.
原理很簡單,
先放一個, 然後放第2個, 第3個,
如果找不到位置, 退回前一列,尋找下一個擺放位置.

為了解決, 擺n個皇後如何處理, 用了一個變數

[code]
  1 #include
  2 #include
  3 #include
  4
  5 void king_dump(char *str, int size)
  6 {
  7         int i;
  8
  9         for(i=0; i 10                  printf("%2d ", str[i] )  ;
 11         }
 12         printf("\n");
 13         /*
 14         char buf[20] ;
 15         buf[size] = 0;
 16
 17         for (i=0; i 18                  memset(buf,'-', size);
 19                  buf[str[i]-1] = '1';
 20                  printf("%s\n",buf);
 21         }
 22         printf("\n");
 23         */
 24
 25
 26 }
 27
 28
 29
 30 int  nking_valid(char *str, int size)
 31 {
 32          int i;
 33          int j = size -1;
 34         /*是否同一斜線,或相等
 35           前面的已經符合規則, 只需判斷最後一個
 36          */
 37
 38          char ch = str[size-1] ;
 39
 40          for(i=0;   i 41                  if (ch == str[i] || abs(ch - str[i]) == j ) {
 42                          return 0;
 43                  }
 44          }
 45          return 1;
 46 }
 47
 48
 49 int nking_next(char *data, int *cur, int max)
 50 {
 51          int i ;
 52          int len = *cur + 2 ;
 53
 54          i = data[len-1] ;
 55          i++;
 56          for (; i<= max ;   i++) {
 57                  data[len-1] =i ;
 58                  if (nking_valid(data, len ) ==1) {
 59                          (*cur)++;
 60                          return 1 ;
 61                  }
 62          }
 63
 64
 65          data[len-1] = 0 ;
 66          /* back trace*/
 67          (*cur) -- ;
 68          return 0;
 69 }
 70
 71 /*
 72    0:空
 73    num: 皇後位置
 74    nking:  回溯法
 75 */
 76
 77
 78 int nking(int nk)
 79 {
 80          char  data[30]={0} ;
 81          int pos =0;
 82          data[0] =1 ;
 83          int lim=nk -1 ;
 84
 85          if (nk>=30) {
 86                  return 0;
 87          }
 88          while (data[0] <=  nk) {
 89                  if (nking_next(data, &pos, nk) ==1) {  /* found corret pos */
 90                          if (pos == lim ) {
 91                                  king_dump(data, nk) ;
 92                                  pos --;
 93                          }
 94                          continue ;
 95                  }
 96                  /* error */
 97                  if (pos <0) {
 98                          pos = 0;
 99                          data[0] +=1 ;
100                  }
101          }
102          return 0;
103 }
104
105
106 int main(int argc, char *argv[])
107 {
108          int i = 8;
109          if (argc>1) {
110                  i =atoi(argv[1]) ;
111
112          }
113
114          nking(i);
115          exit(0);
116
117 }
118
[/code]


阅读(2688) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~