青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

qinzuoyan

  C++博客 :: 首頁 :: 聯(lián)系 :: 聚合  :: 管理
  8 Posts :: 0 Stories :: 16 Comments :: 0 Trackbacks

常用鏈接

留言簿(3)

我參與的團(tuán)隊(duì)

搜索

  •  

最新評(píng)論

閱讀排行榜

評(píng)論排行榜

最近一個(gè)朋友在用計(jì)算機(jī)模擬人來玩文曲星上的“猜數(shù)字”游戲,也邀我一起討論。我以前沒有玩過,不過發(fā)現(xiàn)這個(gè)還是蠻有趣的,于是也想寫一個(gè)能猜數(shù)據(jù)的小程序。

通過幾日思考,終于實(shí)現(xiàn)了一個(gè)稍微有點(diǎn)聰明的。以下是C++代碼(下載源代碼)。

首先函數(shù)頭的定義部分,其中一個(gè)重要的數(shù)據(jù)結(jié)構(gòu)是各個(gè)排列之間的關(guān)系矩陣。
我們使用 char 來表示兩個(gè)排列的關(guān)系,char值的計(jì)算方法為“A*10+B”;譬如假設(shè) 排列i 與 排列j 的關(guān)系為“1A2B”,則 table[i][j] = (char)12。
 1 #include <iostream>
 2 
 3 #define N 4           // 排列長(zhǎng)度
 4 #define M (10*9*8*7)  // 總的可能排列數(shù)
 5 #define MATCH (N*10)  // 猜測(cè)正確時(shí)的judge()返回值
 6 
 7 #define swap(a,b) {int t=a; a=b; b=t;}
 8 
 9 int arrange[M][N];    // 所有可能排列的列表,一行一個(gè)排列
10 char table[M][M];     // 各排列之間的關(guān)系矩陣
11 
12 int arr_count;        // 用于生成所有排列時(shí)使用的全局變量

判斷兩個(gè)排列之間關(guān)系的函數(shù):
 1 // 判斷兩個(gè)排列之間的關(guān)系
 2 // 譬如如果結(jié)果為“1A2B”,則返回值為 (char)12
 3 char judge(int v1[], int v2[])
 4 {
 5     int a = 0;
 6     int b = 0;
 7     for (int i=0; i<N; i++) {
 8         if( v1[i] == v2[i])
 9             a += 1;
10         for (int j=0; j<N; j++) {
11             if (v1[i] == v2[j])
12                 b += 1;
13         }
14     }
15     b -= a;
16     return (char)(a * 10 + b);
17 }
18 

初始化排列列表:
 1 // 使用遞歸方法計(jì)算排列
 2 void arr(int a[], int start)
 3 {
 4     if (start == N) {
 5         for (int i=0; i<N; i++)
 6             arrange[arr_count][i] = a[i];
 7         arr_count++;
 8         return;
 9     }
10     for (int i=start; i<=9; i++) {
11         swap(a[start], a[i]);
12         arr(a, start+1);
13         swap(a[start], a[i]);
14     }
15 }
16 
17 // 初始化所有可能排列情況的列表
18 void init_arrange()
19 {
20     int a[10];
21     arr_count = 0;
22     for (int i=0; i<=9; i++
23         a[i] = i;
24     arr(a, 0);
25 }

初始化關(guān)系矩陣:
1 // 初始化各個(gè)排列間的關(guān)系矩陣
2 void init_table()
3 {
4     for (int i=0; i<M; i++) {
5         for (int j=0; j<=i; j++) {
6             table[i][j] = table[j][i] = judge(arrange[i], arrange[j]);
7         }
8     }
9 }

為了方便,這里有一些打印信息的函數(shù):
 1 // 按照“[0 1 2 3]”的形式打印排列
 2 void print_arrange(int arr_index)
 3 {
 4     std::cout << "[";
 5     for (int i=0; i<N; i++) {
 6         if (i != 0)
 7             std::cout << " ";
 8         std::cout << arrange[arr_index][i];
 9     }
10     std::cout << "]";
11 }
12 
13 // 按照類似“0A0B”的形式打印裁判的結(jié)果
14 void print_result(char result)
15 {
16     std::cout << ((int)result/10<< "A" << ((int)result%10<< "B" <<std::endl;
17 }
18 
19 // 打印一次猜測(cè)與結(jié)果的信息
20 void print_guess_info(int arr_index, char result) {
21     print_arrange(arr_index);
22     std::cout << " --> ";
23     print_result(result);
24     std::cout << std::endl;
25 }

便于擴(kuò)展,使用抽象類。以下是裁判與玩家雙方的接口:
 1 // 玩家的抽象類
 2 class Player
 3 {
 4 public:
 5     // 開始游戲前的初始化
 6     virtual void init() = 0;
 7     // 獲取下一次猜測(cè)的排列
 8     virtual int getNextGuess() = 0;
 9     // 告訴玩家上一次猜測(cè)的結(jié)果
10     virtual void setGuessResult(int arr_index, char result) = 0;
11 };
12 
13 // 裁判的抽象類
14 class Judgment
15 {
16 public:
17     // 開始游戲前的初始化
18     virtual void init() = 0;
19     // 對(duì)猜測(cè)進(jìn)行判斷,返回結(jié)果
20     virtual char doJudge(int arr_index) = 0;
21 };

現(xiàn)在讓玩家玩一次游戲,直到猜成功:
 1 // 玩一次游戲,返回猜測(cè)次數(shù)
 2 int play(Player * p, Judgment * j) {
 3     int time = 0;
 4     p->init();
 5     j->init();
 6     while (1) {
 7         int guess = p->getNextGuess();
 8         char result = j->doJudge(guess);
 9         // print_guess_info(guess, result);
10         time++;
11         if (result == (char)MATCH)
12             break;
13         p->setGuessResult(guess, result);
14     }
15     return time;
16 }

尋找一個(gè)誠(chéng)實(shí)的裁判:
 1 class HonestJudgment
 2     : public Judgment
 3 {
 4     int _my_arr[N];
 5 public:
 6     HonestJudgment() { }
 7     ~HonestJudgment() { }
 8 public:
 9     void init() { }
10     // 設(shè)置裁判的正確結(jié)果
11     void setArrange(int arr[]) {
12         for (int i=0; i<N; i++)
13             _my_arr[i] = arr[i];
14     }
15     // 這是一個(gè)誠(chéng)實(shí)的裁判,所以會(huì)誠(chéng)實(shí)地裁決
16     char doJudge(int arr_index) {
17         return judge(_my_arr, arrange[arr_index]);
18     }
19 };

有了裁判,還要找一個(gè)玩家。我們先找一個(gè)頭腦簡(jiǎn)單點(diǎn)的玩家:
 1 class NaivePlayer
 2     : public Player
 3 {
 4     bool _cand[M];
 5     int _cand_count;
 6 public:
 7     NaivePlayer() { }
 8     ~NaivePlayer() { }
 9 public:
10     void init() {
11         for (int i=0; i<M; i++)
12             _cand[i] = true;
13         _cand_count = M;
14     }
15     int getNextGuess() {
16         // 第一次猜測(cè)總是使用第一個(gè)排列
17         if (_cand_count == M)
18             return 0;
19         // 返回遇到的第一個(gè)可行排列
20         for (int i=0; i<M; i++) {
21             if (_cand[i]) {
22                 return i;
23             }
24         }
25     }
26     void setGuessResult(int arr_index, char result) {
27         // 依據(jù)返回結(jié)果進(jìn)一步排除已有的可行排列
28         for (int j=0; j<M; j++) {
29             if (_cand[j] && table[arr_index][j] != result)
30                 _cand[j] = false;
31             _cand_count--;
32         }
33     }
34 };

用Factory工廠制造裁判和玩家(哈哈,批量生產(chǎn)):
1 Player * player_factory()
2 {
3     return new NaivePlayer();
4 }
5 
6 Judgment * judgment_factory()
7 {
8     return new HonestJudgment();
9 }

現(xiàn)在讓大家玩起來吧:
 1 int main()
 2 {
 3     int time_stat[M]; // 次數(shù)統(tǒng)計(jì)表
 4     Judgment *jp;
 5     Player *pp;
 6     // 獲取實(shí)例
 7     jp = judgment_factory();
 8     pp = player_factory();
 9     // 初始化次數(shù)統(tǒng)計(jì)表
10     for (int i=0; i<M; i++)
11         time_stat[i] = 0;
12     // 初始化排列列表和關(guān)系矩陣
13     init_arrange();
14     init_table();
15     // 每一種排列情況都玩一次
16     for (int i=0; i<M; i++) {
17         ((HonestJudgment*)jp)->setArrange(arrange[i]);
18         int t = play(pp, jp);
19         print_arrange(i);
20         std::cout << " : " << t << std::endl;
21         time_stat[t]++;
22     }
23     // 統(tǒng)計(jì)結(jié)果
24     int total = 0;
25     std::cout << "-------------" << std::endl;
26     for (int i=0; i<M; i++) {
27         if (time_stat[i]) {
28             std::cout << i << "\t" << time_stat[i] << std::endl;
29             total += time_stat[i]*i;
30         }
31     }
32     std::cout << "Average: " << total << "/" << M << " = " << (float)total/<< std::endl;
33     std::cout << "-------------" << std::endl;
34     delete jp;
35     delete pp;
36     return 0;
37 }


得到的統(tǒng)計(jì)數(shù)據(jù):
    NaivePlayer Algorithm:
    
-------------
    
1       1
    
2       13
    
3       108
    
4       596
    
5       1664
    
6       1770
    
7       755
    
8       128
    
9       5
    Average: 
28029/5040 = 5.56131
    
-------------
雖然頭腦簡(jiǎn)單,但是還都能猜出來,只是次數(shù)多了點(diǎn)。

好了,現(xiàn)在整個(gè)框架搭起來了。現(xiàn)在的任務(wù)是尋找更聰明的玩家,讓猜測(cè)次數(shù)降下來。

還真找到了一個(gè)貪婪的玩家(算法原理見代碼注釋),且叫他 Clever1Player 吧:
 1 class Clever1Player
 2     : public Player
 3 {
 4     bool _cand[M]; // 排列是否可行的標(biāo)志矩陣
 5     int _cand_count; // 當(dāng)前可行排列的個(gè)數(shù)
 6 public:
 7     Clever1Player() { }
 8     ~Clever1Player() { }
 9 public:
10     void init() {
11         for (int i=0; i<M; i++)
12             _cand[i] = true;
13         _cand_count = M;
14     }
15     int getNextGuess() {
16         // 第一次猜測(cè)總是使用第一個(gè)排列
17         if (_cand_count == M)
18             return 0;
19         // 當(dāng)只有一個(gè)可行排列時(shí),直接返回
20         if (_cand_count == 1) {
21             for (int i=0; i<M; i++
22                 if (_cand[i])
23                     return i;
24         }
25         ///////////////////
26         // 悲觀假設(shè):
27         //     假設(shè)無論猜什么排列,電腦總是能聰明地返回結(jié)果,
28         //     使得依據(jù)返回結(jié)果能進(jìn)一步排除掉的可行排列數(shù)目最少(即剩余的可行排列數(shù)目最多)
29         // 貪婪算法:
30         //     從可行排列中選擇下一次猜測(cè)的排列;
31         //     在悲觀假設(shè)總是成立的條件下,使得每次排除掉的可行排列數(shù)目最多(即剩余的可行排列數(shù)目最少),即求最好的最壞情況;
32         ///////////////////
33         int res_count[MATCH+1];
34         int min_max = M+1;
35         int min_max_index;
36         for (int i=0; i<M; i++) {
37             // 對(duì)于每一個(gè)可行排列 Ri
38             if (_cand[i]) {
39                 // 下一次猜測(cè)排列 Ri 的時(shí)候,裁判將會(huì)返回一個(gè)結(jié)果;
40                 // 根據(jù)悲觀假設(shè),裁判返回的結(jié)果總是使得依據(jù)返回結(jié)果能進(jìn)一步排除掉的可行排列數(shù)目最少(即剩余的可行排列數(shù)目最多)
41                 // cur_max 記錄該最壞情況下剩余的可行排列的數(shù)目
42                 int cur_max = 0;
43                 for (int j=0; j<=MATCH; j++)
44                     res_count[j] = 0;
45                 for (int j=0; j<M; j++) {
46                     if (_cand[j])
47                         res_count[ (int)table[i][j] ]++;
48                 }
49                 for (int j=0; j<=MATCH; j++)
50                     if (res_count[j] > cur_max)
51                         cur_max = res_count[j];
52                 // 如果 cur_max 小于全局 min_max,則更新 min_max,并記錄下當(dāng)前排列的序號(hào)
53                 // 這樣能找到最好最壞情況
54                 if (cur_max < min_max) {
55                     min_max = cur_max;
56                     min_max_index = i;
57                 }
58             }
59         }
60         // 返回最好最壞情況下的排列序號(hào)
61         return min_max_index;
62     }
63     void setGuessResult(int arr_index, char result) {
64         // 依據(jù)返回結(jié)果進(jìn)一步排除已有的可行排列
65         for (int j=0; j<M; j++) {
66             if (_cand[j] && table[arr_index][j] != result) {
67                 _cand[j] = false;
68                 _cand_count--;
69             }
70         }
71     }
72 };
73 
74 // 讓工廠開始生產(chǎn)我
75 Player * player_factory()
76 {
77     return new Clever1Player();
78 }

好了,Clever1Player 也來玩了,看看他的成績(jī):
    Clever1Player Algorithm:
    
-------------
    
1       1
    
2       13
    
3       108
    
4       620
    
5       2002
    
6       1937
    
7       356
    
8       3
    Average: 
26979/5040 = 5.35298
    
-------------
成績(jī)還不錯(cuò),不過最差情況下要猜8次嘛。

有人說最多7次就可以猜出來,我們?cè)僬艺摇?br>沒想到 Clever1Player 的兄弟 Clever2Player 也會(huì)玩,而且玩的也不錯(cuò)(算法原理見代碼注釋):
 1 class Clever2Player
 2     : public Player
 3 {
 4     bool _cand[M];
 5     int _cand_count;
 6 public:
 7     Clever2Player() { }
 8     ~Clever2Player() { }
 9 public:
10     void init() {
11         for (int i=0; i<M; i++)
12             _cand[i] = true;
13         _cand_count = M;
14     }
15     int getNextGuess() {
16         // 第一次猜測(cè)總是使用第一個(gè)排列
17         if (_cand_count == M)
18             return 0;
19         // 當(dāng)只有一個(gè)可行排列時(shí),直接返回
20         if (_cand_count == 1) {
21             for (int i=0; i<M; i++
22                 if (_cand[i])
23                     return i;
24         }
25         ///////////////////
26         // 與Clever1Player的區(qū)別:
27         //     下一次猜測(cè)的排列不局限于可行排列
28         ///////////////////
29         int res_count[MATCH+1];
30         int min_max = M+1;
31         int min_max_index;
32         for (int i=0; i<M; i++) {
33             // 對(duì)于所有排列 Ri
34             int cur_max = 0;
35             for (int j=0; j<=MATCH; j++)
36                 res_count[j] = 0;
37             for (int j=0; j<M; j++) {
38                 if (_cand[j])
39                     res_count[ (int)table[i][j] ]++;
40             }
41             for (int j=0; j<=MATCH; j++)
42                 if (res_count[j] > cur_max)
43                     cur_max = res_count[j];
44             if (cur_max < min_max) {
45                 min_max = cur_max;
46                 min_max_index = i;
47             }
48         }
49         return min_max_index;
50     }
51     void setGuessResult(int arr_index, char result) {
52         for (int j=0; j<M; j++) {
53             if (_cand[j] && table[arr_index][j] != result) {
54                 _cand[j] = false;
55                 _cand_count--;
56             }
57         }
58     }
59 };
60 
61 // 讓工廠開始生產(chǎn)我
62 Player * player_factory()
63 {
64     return new Clever2Player();
65 }

Clever2Player 的成績(jī):
    Clever2Player Algorithm:
    
-------------
    
1       1
    
2       2
    
3       22
    
4       176
    
5       1301
    
6       2885
    
7       653
    Average: 
29161/5040 = 5.78591
    
-------------
不錯(cuò),果然在7次之內(nèi)都能猜出來。只是為什么平均成績(jī)還不如 Clever1Player 呢?
這個(gè)問題,我得找時(shí)間問問他。

當(dāng)前Clever1Player時(shí)間復(fù)雜度為 (M*M*Time) ,其中Time為猜測(cè)次數(shù)。考慮次數(shù)總小于10,所以時(shí)間復(fù)雜度為 (M^2)。

我曾經(jīng)做過優(yōu)化,即使用一個(gè)數(shù)組保存可行排列序號(hào),這樣在 Clever1Player 的 36 和 45 行就只需要掃描數(shù)組,而不需要每次都掃描 M 次了。當(dāng)然總的時(shí)間復(fù)雜度依然是 (M^2)。

Clever2Player 與 Clever1Player 的唯一區(qū)別在于 “去掉了Clever1Player 的第 38 行”,使得“下一次猜測(cè)的排列不局限于可行排列”。
基于的考慮是:
-------------
假設(shè)正確結(jié)果是 0124
第一次猜 0123 -> 3A0B
Clever1Player 接下來不能猜 4567 ,因?yàn)?4567 不在可行集中(已經(jīng)排除)。
但是Clever2Player 則有可能會(huì)猜 4567 得到 0A1B,直觀上說,猜測(cè)范圍就縮小到 01234567 中了,搜索空間減小很多。實(shí)際上我們?nèi)四X使用邏輯推理的時(shí)候通常就是這么考慮的,而且我們肯定是不會(huì)使用這種搜索算法的。
至于邏輯推理法與搜索法之間有什么聯(lián)系,我也不清楚。
-------------

另外,該算法的關(guān)注點(diǎn)在于猜測(cè)次數(shù),即在于效果而不是效率。所以為了使算法看起來清晰,我沒有過多優(yōu)化。

NaivePlayer 算法執(zhí)行時(shí)間最快,大約1分鐘跑完所有5040種情況,Clever1Player大約5分鐘,Clever2Player大約10分鐘。

另外我也曾考慮過“動(dòng)態(tài)規(guī)劃”算法,遞推公式: t(F) = min{ t(F-f)+1, for all f belongs to F}, 其中 F 是當(dāng)前可行集,t(F) 為該可行集 F 條件下猜出結(jié)果的次數(shù),f 為 F 中的一個(gè)可行排列。
但是我沒有編程實(shí)現(xiàn),因?yàn)閾?dān)心復(fù)雜度太高運(yùn)行不完。
而貪心算法得到的應(yīng)當(dāng)不是最優(yōu)解,但是近似最優(yōu)解,而且從次數(shù)和執(zhí)行效率上來說都是可以接受的。

下一步做什么呢?

我們可以找一個(gè)狡猾的裁判,他讓玩家 Clever1Player 和 Clever1Player 的“悲觀假設(shè)”變成現(xiàn)實(shí)。
一邊是聰明的玩家,一邊是狡猾的裁判,哈哈,有好戲看了。
究竟鹿死誰手,請(qǐng)聽下回分解。

最后感謝東坡_居士,讓我有機(jī)會(huì)接觸這么好玩的游戲。

posted on 2009-08-14 14:11 左言 閱讀(3209) 評(píng)論(15)  編輯 收藏 引用

Feedback

# re: 文曲星“猜數(shù)字”游戲的計(jì)算機(jī)模擬 —— 算法分析與實(shí)現(xiàn) 2009-08-14 14:41 東坡_居士
Clever1Player 思路基本了解了,Clever2Player 不明白
程序沒看,感覺看不懂c++面向?qū)ο罅恕!!?

還有一個(gè)問題,這個(gè)程序復(fù)雜度多少啊?或者說跑出這個(gè)結(jié)果要多久?  回復(fù)  更多評(píng)論
  

# re: 文曲星“猜數(shù)字”游戲的計(jì)算機(jī)模擬 —— 算法分析與實(shí)現(xiàn) 2009-08-14 15:04 左言
@東坡_居士

當(dāng)前Clever1Player時(shí)間復(fù)雜度為 (M*M*Time) ,其中Time為猜測(cè)次數(shù)。考慮次數(shù)總小于10,所以時(shí)間復(fù)雜度為 (M^2)。

我曾經(jīng)做過優(yōu)化,即使用一個(gè)數(shù)組保存可行排列序號(hào),這樣在 Clever1Player 的 36 和 45 行就只需要掃描數(shù)組,而不需要每次都掃描 M 次了。當(dāng)然總的時(shí)間復(fù)雜度依然是 (M^2)。

Clever2Player 與 Clever1Player 的唯一區(qū)別在于 “去掉了Clever1Player 的第 38 行”,使得“下一次猜測(cè)的排列不局限于可行排列”。
基于的考慮是:
-------------
假設(shè)正確結(jié)果是 0124
第一次猜 0123 -> 3A0B
Clever1Player 接下來不能猜 4567 ,因?yàn)?4567 不在可行集中(已經(jīng)排除)。
但是Clever2Player 則有可能會(huì)猜 4567 得到 0A1B,直觀上說,猜測(cè)范圍就縮小到 01234567 中了,搜索空間減小很多。實(shí)際上我們?nèi)四X使用邏輯推理的時(shí)候通常就是這么考慮的,而且我們肯定是不會(huì)使用這種搜索算法的。
至于邏輯推理法與搜索法之間有什么聯(lián)系,我也不清楚。
-------------

另外,該算法的關(guān)注點(diǎn)在于猜測(cè)次數(shù),即在于效果而不是效率。所以為了使算法看起來清晰,我沒有過多優(yōu)化。

NaivePlayer 算法執(zhí)行時(shí)間最快,大約1分鐘跑完所有,Clever1Player大約5分鐘,Clever2Player大約10分鐘。


  回復(fù)  更多評(píng)論
  

# re: 文曲星“猜數(shù)字”游戲的計(jì)算機(jī)模擬 —— 算法分析與實(shí)現(xiàn) 2009-08-14 15:17 東坡_居士
恩,確實(shí)可以用可行解之外的做試探,我之前也想到這點(diǎn),總感覺不可思議,猶豫之下為了少算幾次就沒用了~

找最好最壞那一步再描述一下?是否有遞歸啊?是否對(duì)算過的集合做記錄?  回復(fù)  更多評(píng)論
  

# re: 文曲星“猜數(shù)字”游戲的計(jì)算機(jī)模擬 —— 算法分析與實(shí)現(xiàn) 2009-08-14 15:18 左言
@東坡_居士


回復(fù)東坡_居士:你的算法“如果這個(gè)“提問”得到的“答案”種類越多,每個(gè)答案下面的可能數(shù)字就越少”,實(shí)際上可以通過對(duì)Clever1Palyer的進(jìn)行修改實(shí)現(xiàn):
34 int all_max = 0;
35 int all_max_index;
36 for (int i=0; i<M; i++) {
37 // 對(duì)于每一個(gè)可行排列 Ri
38 if (_cand[i]) { // 這一行也可以去掉
41 // cur_max 記錄該當(dāng)前行可行排列的關(guān)系的種數(shù)
42 int cur_max = 0;
43 for (int j=0; j<=MATCH; j++)
44 res_count[j] = 0;
45 for (int j=0; j<M; j++) {
46 if (_cand[j])
47 res_count[ (int)table[i][j] ]++;
48 }
49 for (int j=0; j<=MATCH; j++) // 求種類數(shù)
50 if (res_count[j] > 0)
51 cur_max ++;
52 // 如果 cur_max 小于全局 all_max,則更新 all_max,并記錄下當(dāng)前排列的序號(hào)
53 // 這樣能找到種類數(shù)最多的情況
54 if (cur_max > all_max) {
55 all_max = cur_max;
56 all_max_index = i;
57 }
58 }
59 }

所以我的假設(shè)是最壞假設(shè),你的假設(shè)是等概率假設(shè)。呵呵,你把裁判想得比較善良。
  回復(fù)  更多評(píng)論
  

# re: 文曲星“猜數(shù)字”游戲的計(jì)算機(jī)模擬 —— 算法分析與實(shí)現(xiàn) 2009-08-14 15:22 左言
@東坡_居士
最好最壞就是說:每一行求最大(最壞),然后對(duì)所有行的最大值中取最小(最好)。所以計(jì)算過程還是 O(M^2) 的。  回復(fù)  更多評(píng)論
  

# re: 文曲星“猜數(shù)字”游戲的計(jì)算機(jī)模擬 —— 算法分析與實(shí)現(xiàn) 2009-08-14 15:32 東坡_居士
@左言
恩,我理解錯(cuò)了~

我之前想的新的思路是這樣:

因?yàn)閱栴}的根源都在于我們?cè)鯓釉u(píng)價(jià)一個(gè)狀態(tài)的好壞,我們現(xiàn)在都用數(shù)字的多少區(qū)評(píng)價(jià),數(shù)字越多越糟糕。這個(gè)評(píng)價(jià)還是很初級(jí)簡(jiǎn)單的。

顯然,既然求最小步數(shù),那么最準(zhǔn)確的評(píng)價(jià)就是,這個(gè)狀態(tài)可以(平均、最壞)多少步得到解。

但是,這個(gè)評(píng)價(jià)標(biāo)準(zhǔn)需要遞歸(太慢,我測(cè)試9876用了十幾分鐘),或者記錄狀態(tài)(太大存不下)

我現(xiàn)在在想這個(gè)的優(yōu)化~希望在可接受時(shí)間內(nèi)跑出所有解~  回復(fù)  更多評(píng)論
  

# re: 文曲星“猜數(shù)字”游戲的計(jì)算機(jī)模擬 —— 算法分析與實(shí)現(xiàn) 2009-08-14 15:44 左言
@東坡_居士
我猜測(cè)你也在考慮“動(dòng)態(tài)規(guī)劃”方法。
我考慮過“動(dòng)態(tài)規(guī)劃”算法,遞推公式: t(F) = min{ t(F-f)+1, for all f belongs to F}, 其中 F 是當(dāng)前可行集,t(F)為該可行集 F 條件下猜出結(jié)果的次數(shù),f 為 F 中的一個(gè)可行排列。
但是我沒有編程實(shí)現(xiàn),因?yàn)閾?dān)心復(fù)雜度太高運(yùn)行不完。但是可以保證這樣能得到最優(yōu)解。
貪心算法得到的應(yīng)當(dāng)不是最優(yōu)解,但是近似最優(yōu)解,而且也是可以接受的。  回復(fù)  更多評(píng)論
  

# re: 文曲星“猜數(shù)字”游戲的計(jì)算機(jī)模擬 —— 算法分析與實(shí)現(xiàn) 2009-08-14 15:49 左言
@東坡_居士
上面公式還可以進(jìn)一步修改一下:
t(F) = min{ t( F- conf(f) ) + 1, for all f belongs to F}, 其中conf(f)指與f沖突的集合(每一種返回結(jié)果就對(duì)應(yīng)一個(gè)沖突集,所以復(fù)雜度又上升了)。  回復(fù)  更多評(píng)論
  

# re: 文曲星“猜數(shù)字”游戲的計(jì)算機(jī)模擬 —— 算法分析與實(shí)現(xiàn) 2009-08-14 15:55 東坡_居士
@左言

恩,是這樣,我現(xiàn)在覺得能存下來,不過需要hash一下,時(shí)間上應(yīng)該還行,一兩個(gè)小時(shí)我也認(rèn)了~呵呵~

還有一個(gè)問題是這樣,在一個(gè)可行解集合里,每一個(gè)數(shù)的概率是一樣的吧?  回復(fù)  更多評(píng)論
  

# re: 文曲星“猜數(shù)字”游戲的計(jì)算機(jī)模擬 —— 算法分析與實(shí)現(xiàn) 2009-08-14 16:06 左言
@東坡_居士

我覺得不應(yīng)當(dāng)考慮概率,而應(yīng)當(dāng)考慮在任意時(shí)刻,可行解集合里任何數(shù)都有可能是正確結(jié)果。實(shí)際上就是在一個(gè)狀態(tài)轉(zhuǎn)移圖中,任何可行的路徑都有可能沿著走下去,每選擇一個(gè)數(shù),就走進(jìn)了一個(gè)分支。
  回復(fù)  更多評(píng)論
  

# re: 文曲星“猜數(shù)字”游戲的計(jì)算機(jī)模擬 —— 算法分析與實(shí)現(xiàn) 2009-08-15 06:54 空明流轉(zhuǎn)
我當(dāng)年就是直接枚舉法的,沒搞那么復(fù)雜。。。  回復(fù)  更多評(píng)論
  

# re: 文曲星“猜數(shù)字”游戲的計(jì)算機(jī)模擬 —— 算法分析與實(shí)現(xiàn) 2009-08-15 11:35 凡客誠(chéng)品
沒搞那么復(fù)雜。。。   回復(fù)  更多評(píng)論
  

# re: 文曲星“猜數(shù)字”游戲的計(jì)算機(jī)模擬 —— 算法分析與實(shí)現(xiàn) 2009-08-15 20:05 左言
@空明流轉(zhuǎn)

直接枚舉法,你說的是對(duì)5040種排列依次猜測(cè)嗎。。。?最壞情況下猜測(cè)次數(shù)可能5040次吧。或者你有更好的辦法嗎?
  回復(fù)  更多評(píng)論
  

# re: 文曲星“猜數(shù)字”游戲的計(jì)算機(jī)模擬 —— 算法分析與實(shí)現(xiàn) 2010-05-06 18:48 zt
通過信息熵來看,最少的次數(shù)應(yīng)該是3.7次。所以還是有些開發(fā)的空間。。求大牛啊。  回復(fù)  更多評(píng)論
  

# re: 文曲星“猜數(shù)字”游戲的計(jì)算機(jī)模擬 —— 算法分析與實(shí)現(xiàn)[未登錄] 2011-01-27 17:35 zz
你這不嚴(yán)謹(jǐn)啊。這個(gè)問題其實(shí)就是博弈,電腦想成會(huì)變卦的電腦,猜數(shù)的步數(shù)取判決步數(shù)中最大的,判決步數(shù)取猜數(shù)字最小的  回復(fù)  更多評(píng)論
  


只有注冊(cè)用戶登錄后才能發(fā)表評(píng)論。
網(wǎng)站導(dǎo)航: 博客園   IT新聞   BlogJava   博問   Chat2DB   管理


青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            免费一级欧美片在线观看| 亚洲高清在线精品| 亚洲视频一区在线| 欧美日本在线视频| 亚洲一区二区三区精品在线观看| 亚洲精品久久久久久久久| 欧美日韩亚洲三区| 欧美制服丝袜| 久久久久一区二区| 亚洲精品一区二区网址 | 国产精品久久久久9999| 欧美一区二区视频在线| 久久精品亚洲乱码伦伦中文 | 国产性猛交xxxx免费看久久| 久久亚洲春色中文字幕| 欧美成年人视频网站| 亚洲欧美国产三级| 欧美激情综合五月色丁香| 亚洲激情视频在线观看| 亚洲美女中文字幕| 国产一区二区日韩| 亚洲福利av| 国产精品影视天天线| 免费在线观看成人av| 欧美日韩亚洲视频一区| 久久人91精品久久久久久不卡| 开心色5月久久精品| 亚洲一线二线三线久久久| 欧美亚洲综合在线| 亚洲午夜一区二区| 久久久噜噜噜久久狠狠50岁| 亚洲私人黄色宅男| 免费观看亚洲视频大全| 久久不见久久见免费视频1| 欧美大胆人体视频| 噜噜噜噜噜久久久久久91| 国产精品theporn88| 欧美成年人视频| 国产日韩欧美精品在线| 一本久久综合| 亚洲理伦在线| 久久午夜精品| 久久久精品性| 国产精品久久久久久一区二区三区| 欧美电影在线播放| 经典三级久久| 欧美一级视频| 亚欧成人在线| 国产精品高清在线| 日韩视频免费在线观看| 亚洲韩日在线| 久久综合亚州| 男女精品网站| 亚洲国产福利在线| 久久久精品欧美丰满| 久久激五月天综合精品| 国产精品一区二区三区乱码| 99精品视频免费| 日韩视频精品| 欧美精品一区二区蜜臀亚洲 | 亚洲一区二区欧美日韩| 欧美精品激情在线观看| 欧美激情欧美狂野欧美精品| 亚洲电影欧美电影有声小说| 久久久精品999| 免费不卡亚洲欧美| 亚洲大片精品永久免费| 久久久综合免费视频| 免费观看欧美在线视频的网站| 国产亚洲女人久久久久毛片| 欧美在线一级va免费观看| 久久免费少妇高潮久久精品99| 好吊色欧美一区二区三区四区 | 欧美日韩一区二区精品| 一本色道久久综合亚洲精品高清 | 亚洲欧美制服中文字幕| 久久蜜桃香蕉精品一区二区三区| 亚洲经典在线| 欧美成人网在线| 亚洲精品中文字幕在线| 亚洲在线观看| 国产精品视频内| 久久成人免费| 亚洲国产天堂久久综合| 亚洲视频在线观看免费| 国产麻豆日韩| 久久艳片www.17c.com| 亚洲精品永久免费| 久久福利电影| 亚洲人www| 国产精品美女主播| 久久久久久久久久久久久女国产乱| 欧美91大片| 亚洲尤物视频网| 国产一区二区三区在线观看免费视频| 久久午夜精品一区二区| 日韩视频在线一区二区三区| 久久国产婷婷国产香蕉| 亚洲国产精品高清久久久| 国产精品久久久一区麻豆最新章节| 新67194成人永久网站| 亚洲激情视频在线| 久久乐国产精品| 国产精品99久久久久久久久久久久| 国产亚洲欧美一区二区三区| 欧美日韩精品在线| 久久婷婷人人澡人人喊人人爽| 亚洲精品一区二区三区四区高清| 久久成人精品电影| 99这里只有久久精品视频| 国产一区二区主播在线| 欧美日韩久久不卡| 久热精品在线| 午夜久久一区| 一区二区高清在线观看| 欧美高清在线视频| 久久精品国产免费看久久精品| 一区二区三区高清在线| 亚洲国产精品视频| 国内精品99| 国产欧美精品一区| 国产精品xxxav免费视频| 欧美黄色一区二区| 免费观看成人| 久久久久欧美精品| 欧美在线一级va免费观看| 亚洲一区二区三区四区视频| 亚洲老司机av| 91久久极品少妇xxxxⅹ软件| 欧美77777| 欧美国产日本| 欧美成人免费小视频| 另类亚洲自拍| 久久一区欧美| 久久久久国产精品www| 欧美专区在线观看| 欧美一区二区视频在线观看2020| 亚洲午夜激情网页| 亚洲一二三区在线观看| 亚洲视频在线一区| 亚洲视频福利| 亚洲一级网站| 欧美一区视频| 久久精品中文字幕一区| 久久蜜桃av一区精品变态类天堂| 久久精品女人的天堂av| 久久先锋资源| 美女黄网久久| 亚洲国产精品va在线看黑人| 亚洲国产99| 99国产精品久久久久久久| 亚洲私人影院在线观看| 亚洲欧美日韩国产精品| 欧美一区二区三区四区高清| 欧美专区一区二区三区| 影音先锋亚洲精品| 亚洲国语精品自产拍在线观看| 在线成人av网站| 亚洲人成欧美中文字幕| 中文日韩在线| 欧美一区二区成人6969| 裸体丰满少妇做受久久99精品| 欧美大尺度在线| 亚洲人成高清| 亚洲免费视频中文字幕| 久久国产婷婷国产香蕉| 久久午夜精品一区二区| 欧美日韩国产亚洲一区 | 久久久精品国产99久久精品芒果| 裸体一区二区三区| 欧美体内she精视频在线观看| 国产精品制服诱惑| 亚洲精品123区| 亚洲永久在线| 欧美高清在线| 午夜精品久久久久久99热| 久久综合一区二区| 国产精品拍天天在线| 在线观看视频免费一区二区三区| 99爱精品视频| 久久久久天天天天| 一本色道**综合亚洲精品蜜桃冫| 午夜亚洲视频| 欧美日韩国产另类不卡| 国产一区二区三区在线观看免费视频| 亚洲精品国产精品国自产在线| 亚洲影院在线| 亚洲国产小视频| 欧美亚洲免费高清在线观看| 欧美激情综合| 1024成人| 久久婷婷国产综合国色天香| 一区二区日韩免费看| 理论片一区二区在线| 国产欧美一区视频| 亚洲免费视频观看| 亚洲国产一区视频| 老鸭窝毛片一区二区三区| 国产亚洲欧美一区二区| 亚洲欧美综合v|