RSS   



  可打印版本 | 推薦給朋友 | 訂閱主題 | 收藏主題 | 純文字版  


 


 
主題: [資訊電機] [求助]精典題型八皇后...   字型大小:||| 
Acute
論壇第一大毒王
等級: 18等級: 18等級: 18等級: 18等級: 18
論壇第一小神童

 . 積分: 3281
 . 精華: 8
 . 文章: 11574
 . 收花: 14037 支
 . 送花: 3260 支
 . 比例: 0.23
 . 在線: 323 小時
 . 瀏覽: 2250 頁
 . 註冊: 8020
 . 失蹤: 5372
#1 : 2005-4-10 05:34 PM     全部回覆 引言回覆

皇后在西洋棋裏面, 只能走橫直兩條路
所以, 一個8x8 的棋盤, 可以讓8 個皇后各據一位置而不會互相侵犯
因此, 程式重點在於, 在放上第一個皇后之後, 搜索整個盤面, 把其他皇后逐一擺上去
擺法就是, 放上去的位置, 在橫向跟縱向都不會遇到另一個皇后
最簡單的方法, 就是用一個8x8 的二維陣列, 剛開始全部設為0
皇后一旦確定位置, 就設為1, 這樣子, 只要檢查縱橫方向有沒有不為零, 就知道能不能放皇后了

至於寫法上... 應該有各種方法吧... 看你要用啥方法應該都可以
你可以先寫了, 再Post 出來討論, 不然也不知道你有遇到啥困難勒

如果題目只是把8 個皇后擺上去, 問題就變得很單純
如果是要求, 算出可以有幾種擺法, 那就比較複雜
因為需要確認每個擺法是否曾經出現過, 呵

Acute.



[如果你喜歡本文章,就按本文章之鮮花~送花給作者吧,你的支持就是別人的動力來源]
本文連接  
檢閱個人資料  發私人訊息  Blog  新增/修改 爬文標記
Acute
論壇第一大毒王
等級: 18等級: 18等級: 18等級: 18等級: 18
論壇第一小神童

 . 積分: 3281
 . 精華: 8
 . 文章: 11574
 . 收花: 14037 支
 . 送花: 3260 支
 . 比例: 0.23
 . 在線: 323 小時
 . 瀏覽: 2250 頁
 . 註冊: 8020
 . 失蹤: 5372
#2 : 2005-4-11 03:28 AM     全部回覆 引言回覆

呵呵... sorry, 是我記錯了 ^^"
橫直斜都不能放
sfredr... 你那個程式是你寫的吧?
嚴重不對哩 @_@
至少要8x8 的二維陣列, 才有辦法記錄一個棋盤
你只用一維陣列... 是無法記錄的喔

還有, 你的題目是要擺出一個? 還是求出所有解?
兩個相差很多很多哩 @_@

Acute.



[如果你喜歡本文章,就按本文章之鮮花~送花給作者吧,你的支持就是別人的動力來源]
本文連接  
檢閱個人資料  發私人訊息  Blog  新增/修改 爬文標記
Acute
論壇第一大毒王
等級: 18等級: 18等級: 18等級: 18等級: 18
論壇第一小神童

 . 積分: 3281
 . 精華: 8
 . 文章: 11574
 . 收花: 14037 支
 . 送花: 3260 支
 . 比例: 0.23
 . 在線: 323 小時
 . 瀏覽: 2250 頁
 . 註冊: 8020
 . 失蹤: 5372
#3 : 2005-4-11 05:07 AM     全部回覆 引言回覆

呵, 我沒有細看你程式如何記錄, sorry ^^"
跑出來就好
如果要去除回圈, 就得使用遞回的方式寫
例如: (我按照你程式的結構改的, 等於只改掉main & 加一個遞回程序, 其餘一樣)

int rows[Q];  //變數改到這兒, 減少參數傳遞, 免得更慢
void Queen (int i)
{
   if ( i < Q )
      for (rows[i]=0 ; rows[i] < Q ; rows[i]++)
         Queen (i+1);
   else if (valid(rows))
      printAnswer(rows);
}

int main()
{

   Queen(0);
   printf("一共有%d組解\n",count);
}
上面的方式, 只是單純的去除迴圈, 變成遞迴模式
基本上, 程式應該會比你原來的跑的更慢, 因為遞迴不是加速, 而是讓程式變得簡單
要加速的話, 就必須導入資料結構的一些方法, 減少不必要的retry
通常在資料結構裏面, 都是介紹用tree 的方法
PS: 程式我沒測試喔, 但是應該不會錯啦 ^^"
      只是簡單的去迴圈, 應該不至於敲錯才對

Acute.

[Acute 在 2005-4-11 05:09 AM 作了最後編輯]



[如果你喜歡本文章,就按本文章之鮮花~送花給作者吧,你的支持就是別人的動力來源]
本文連接  
檢閱個人資料  發私人訊息  Blog  新增/修改 爬文標記
Acute
論壇第一大毒王
等級: 18等級: 18等級: 18等級: 18等級: 18
論壇第一小神童

 . 積分: 3281
 . 精華: 8
 . 文章: 11574
 . 收花: 14037 支
 . 送花: 3260 支
 . 比例: 0.23
 . 在線: 323 小時
 . 瀏覽: 2250 頁
 . 註冊: 8020
 . 失蹤: 5372
#4 : 2005-4-11 05:19 AM     全部回覆 引言回覆

嗯... 忽然想到... 多加一個去除同樣的迴圈, 應該就可以加速了
也就是, 上面那個遞迴函式改為:

void Queen (int i)
{
   int j ;

   if ( i < Q )
      for (rows[i]=0 ; rows[i] < Q ; )  // 這兒不遞加, 由新增loop 決定
      {
         Queen (i+1);
         rows[i]++ ;                        // 原本上層迴圈最後+1 搬到這兒
         for ( j=0 ; j < i ; j++ )          // 增加檢查是否已經跟以前重複的迴圈
            if ( rows[j] == rows[i] )     // 如果已經重複,
               rows[i]++ ;                  //       則直接跳過該值, 換下一個
      }
   else if (valid(rows))
      printAnswer(rows);
}
多加一個loop決定下一次要try 的數值
這樣子, 理論上程式執行時間, 應該變成上一個的約... 1/8 時間
而且, 這種程式要遞迴模式才可以寫
不然每層迴圈內都要加一層這種code, 程式會看得眼花撩亂, 呵

Acute.



[如果你喜歡本文章,就按本文章之鮮花~送花給作者吧,你的支持就是別人的動力來源]
本文連接  
檢閱個人資料  發私人訊息  Blog  新增/修改 爬文標記
Acute
論壇第一大毒王
等級: 18等級: 18等級: 18等級: 18等級: 18
論壇第一小神童

 . 積分: 3281
 . 精華: 8
 . 文章: 11574
 . 收花: 14037 支
 . 送花: 3260 支
 . 比例: 0.23
 . 在線: 323 小時
 . 瀏覽: 2250 頁
 . 註冊: 8020
 . 失蹤: 5372
#5 : 2005-4-11 06:13 PM     全部回覆 引言回覆


引用:
GERRYccc寫到:

引用:
Acute寫到:
...

void Queen (int i)
{
   int j ;

   if ( i < Q )
      for (rows[ i ]=0 ; rows[ i ] < Q ; )  // 這兒不遞加, 由新增loop 決定
      {
         Queen (i+1);
         rows[ i ]++ ;                        // 原本上層迴圈最後+1 搬到這兒
         for ( j=0 ; j < i ; j++ )          // 增加檢查是否已經跟以前重複的迴圈
            if ( rows[ j ] == rows[ i ] )     // 如果已經重複,
               rows[ i ]++ ;                  //       則直接跳過該值, 換下一個
      }
   else if (valid(rows))
      printAnswer(rows);
}

...
Acute.


嘿嘿,又抓到一個地方了…難怪一直編譯錯誤! 希望不要又抓錯
使用DEV-C++ 上面紅色部分無法編譯!且原 sfredr 兄 給我的程式碼(非版面上
也不是用printAnswer 呵呵…
上面紅色字改成 answer(rows); 即可正常編譯!
阿Q給花給花有兩篇皆有同樣錯…30朵



我真是被你打敗
你自己都會說, 你手上的程式非版面上的
那我是看版面上的東西回的, 當然按照版面上的
請去看原始Post 出來的程式碼, 就是用printAnswer 嘿嘿...
so... 反過來, 你欠我30朵花

Acute.



[如果你喜歡本文章,就按本文章之鮮花~送花給作者吧,你的支持就是別人的動力來源]
本文連接  
檢閱個人資料  發私人訊息  Blog  新增/修改 爬文標記
Acute
論壇第一大毒王
等級: 18等級: 18等級: 18等級: 18等級: 18
論壇第一小神童

 . 積分: 3281
 . 精華: 8
 . 文章: 11574
 . 收花: 14037 支
 . 送花: 3260 支
 . 比例: 0.23
 . 在線: 323 小時
 . 瀏覽: 2250 頁
 . 註冊: 8020
 . 失蹤: 5372
#6 : 2005-4-12 01:24 PM     全部回覆 引言回覆

假設你問我好了.... 因為你沒說哪個迴圈的rows[j] @_@
加速的方式很簡單, 每一層迴圈的下一個數值, 都先檢查前面幾層已經產生的數值
如果重複, 就已經是不可能的, 所以就不用拿去嘗試了, 可以直接檢查下一個數值

^^" 加速後的程式, 預估是剩下原來時間的1/8
這是因為我假設負載平衡的條件算的, 實際上應該更快
因為遞迴裏面的判斷式只判斷一個條件, 而valid() 裏面則有很複雜的判斷式
所以, 我應該可以確定實際上執行時間不到原來的1/8
當然, 這也是有數學原理的 ^^"

通常演算法的課程, 會提到這方面的數學模型推論
當然, 可以不用那麼複雜啦, 用最簡單的數學就可以進行簡易評估
^^" 誰想嘗試推論一下數學式阿, ccc

Acute.



[如果你喜歡本文章,就按本文章之鮮花~送花給作者吧,你的支持就是別人的動力來源]
本文連接  
檢閱個人資料  發私人訊息  Blog  新增/修改 爬文標記

   



 



所在時區為 GMT+8, 現在時間是 2024-5-10 09:20 AM
清除 Cookies - 連絡我們 - TWed2k © 2001-2046 - 純文字版 - 說明
Discuz! 0.1 | Processed in 0.024848 second(s), 7 queries , Qzip disabled