窮舉搜索

窮舉搜索

實質(zhì)是創(chuàng)建一個狀態(tài)樹,邊建立邊剪枝,得到最終狀態(tài)輸出
步驟有:

  1. 列出表示狀態(tài)的數(shù)據(jù)結(jié)構(gòu)
  2. 列出在狀態(tài)之間遷移的動作的數(shù)據(jù)結(jié)構(gòu)
  3. 列出兩個狀態(tài)轉(zhuǎn)換的所有動作列表
  4. 創(chuàng)建一個deque存儲搜索的狀態(tài)
  5. 從deque尾端取出狀態(tài),判斷是否是最終狀態(tài),是的話打印當(dāng)前deque,進行搜索search,循環(huán)所有動作,執(zhí)行動作searchOnOneAction
  6. 判斷新狀態(tài)是否有效,有效則加入deque,繼續(xù)遞歸調(diào)用搜索

有很多問題用到窮舉搜索,比如過河問題

三個和尚和三個妖怪過河
船只能載兩個
任何時候只要妖怪?jǐn)?shù)量大于和尚數(shù)量
妖怪就要吃掉和尚
求解過河方案

這個問題首先確定狀態(tài)的數(shù)據(jù)結(jié)構(gòu),狀態(tài)就是兩岸monk和monster的數(shù)量,同時有一些配套操作

  • 判斷是否是最終狀態(tài)
  • 狀態(tài)遷移
  • 判斷狀態(tài)是否有效
class ItemState{
friend  ostream& operator<<(ostream&, const ItemState&);
public:
    bool operator==(const ItemState&);
    bool isFinalState();
    bool takeAction(ItemState& next, const ACTION_EFFECTION& action);
    bool isValid();
    int local_monster;
    int local_monk;
    int remote_monster;
    int remote_monk;
    BOAT_LOCATION boat;
};

動作有如下定義

typedef enum{
    ONE_MONSTER_GO = 0,
    TWO_MONSTER_GO,
    ONE_MONK_GO,
    TWO_MONK_GO,
    ONR_MONSTER_ONE_MONK_GO,
    ONE_MONSTER_BACK,
    TWO_MONSTER_BACK,
    ONE_MONK_BACK,
    TWO_MONK_BACK,
    ONR_MONSTER_ONE_MONK_BACK,
    INVALID_ACTION_NAME,
}ACTION_NAME;   
    
typedef struct{
    ACTION_NAME act;
    BOAT_LOCATION boat_to;
    int move_monster;
    int move_monk;
}ACTION_EFFECTION;

得到action的列表,作為窮舉的依據(jù)

static ACTION_EFFECTION actEffect[] =
{
    {ONE_MONSTER_GO,            REMOTE, -1, 0},
    {TWO_MONSTER_GO,            REMOTE, -2, 0},
    {ONE_MONK_GO,               REMOTE, 0,  -1},
    {TWO_MONK_GO,               REMOTE, 0,  -2},
    {ONR_MONSTER_ONE_MONK_GO,   REMOTE, -1, -1},
    {ONE_MONSTER_BACK,          LOCAL,  1,  0},
    {TWO_MONSTER_BACK,          LOCAL,  2,  0},
    {ONE_MONK_BACK,             LOCAL,  0,  1},
    {TWO_MONK_BACK,             LOCAL,  0,  2},
    {ONR_MONSTER_ONE_MONK_BACK, LOCAL,  1,  1}
};

搜索時

void searchState(deque<ItemState> &states)
{
    int act;
    ItemState current = states.back();
    if(current.isFinalState())
    {
        printResult(states);
        return;
    }
    for(act = 0; act < INVALID_ACTION_NAME; act++)
    {
        //debug_out << act <<endl;
        searchStateOnOneAction(states, current, actEffect[act]);
    }
}

void searchStateOnOneAction(deque<ItemState> &states, ItemState &current, ACTION_EFFECTION& actEff)
{
    ItemState next;
    bool canTackAction;
    canTackAction = current.takeAction(next, actEff);
    //debug_out << next;
    if(canTackAction && !isProcessed(states, next))
    {
        //debug_out << "valid" << endl;
        // printResult(states);
        states.push_back(next);
        searchState(states);
        states.pop_back();
    }
}

兩個函數(shù)起到了遞歸的作用,同時使用deque避免出現(xiàn)環(huán)路

bool isProcessed(deque<ItemState> &states, ItemState& state)
{
    auto it = states.end();
    it = find_if(states.begin(), states.end(), [&](ItemState& s){return s==state;});
    return(it!=states.end());
}

完整代碼見https://github.com/lclei/algorithm_fun/tree/master/MonkAndMonster

最后的找到了四種方案

o stands for monk, and x stands for monster.
3o  ||  0o
3x  ||  0x
boat||    

3o  ||  0o
1x  ||  2x
    ||boat

3o  ||  0o
2x  ||  1x
boat||    

3o  ||  0o
0x  ||  3x
    ||boat

3o  ||  0o
1x  ||  2x
boat||    

1o  ||  2o
1x  ||  2x
    ||boat

2o  ||  1o
2x  ||  1x
boat||    

0o  ||  3o
2x  ||  1x
    ||boat

0o  ||  3o
3x  ||  0x
boat||    

0o  ||  3o
1x  ||  2x
    ||boat

0o  ||  3o
2x  ||  1x
boat||    

0o  ||  3o
0x  ||  3x
    ||boat

o stands for monk, and x stands for monster.
3o  ||  0o
3x  ||  0x
boat||    

3o  ||  0o
1x  ||  2x
    ||boat

3o  ||  0o
2x  ||  1x
boat||    

3o  ||  0o
0x  ||  3x
    ||boat

3o  ||  0o
1x  ||  2x
boat||    

1o  ||  2o
1x  ||  2x
    ||boat

2o  ||  1o
2x  ||  1x
boat||    

0o  ||  3o
2x  ||  1x
    ||boat

0o  ||  3o
3x  ||  0x
boat||    

0o  ||  3o
1x  ||  2x
    ||boat

1o  ||  2o
1x  ||  2x
boat||    

0o  ||  3o
0x  ||  3x
    ||boat

o stands for monk, and x stands for monster.
3o  ||  0o
3x  ||  0x
boat||    

2o  ||  1o
2x  ||  1x
    ||boat

3o  ||  0o
2x  ||  1x
boat||    

3o  ||  0o
0x  ||  3x
    ||boat

3o  ||  0o
1x  ||  2x
boat||    

1o  ||  2o
1x  ||  2x
    ||boat

2o  ||  1o
2x  ||  1x
boat||    

0o  ||  3o
2x  ||  1x
    ||boat

0o  ||  3o
3x  ||  0x
boat||    

0o  ||  3o
1x  ||  2x
    ||boat

0o  ||  3o
2x  ||  1x
boat||    

0o  ||  3o
0x  ||  3x
    ||boat

o stands for monk, and x stands for monster.
3o  ||  0o
3x  ||  0x
boat||    

2o  ||  1o
2x  ||  1x
    ||boat

3o  ||  0o
2x  ||  1x
boat||    

3o  ||  0o
0x  ||  3x
    ||boat

3o  ||  0o
1x  ||  2x
boat||    

1o  ||  2o
1x  ||  2x
    ||boat

2o  ||  1o
2x  ||  1x
boat||    

0o  ||  3o
2x  ||  1x
    ||boat

0o  ||  3o
3x  ||  0x
boat||    

0o  ||  3o
1x  ||  2x
    ||boat

1o  ||  2o
1x  ||  2x
boat||    

0o  ||  3o
0x  ||  3x
    ||boat
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容