2023.10.30 学习笔记(野人过河)

题目描述

有三个野人三个道士,他们在何的右岸,现有一艘只能容纳两个人的小船,因为野人比较野蛮,如果河一侧野人的数量大于道士的数量,野人就会攻击道士,问如何安全的过河。输出任意一种方案。

问题分析

这道题目可以通过搜索来实现,广搜和深搜均可,在这里为了锻炼使用广搜的代码能力,笔者决定用广搜来解答这道题目。

为了进行广搜我们需要创建一个三元组$(x, (y, z))$,分别代表着河右岸道士的人数,野人的人数,船在左侧还是在右侧,其中记 $1$ 为船在右侧,记 $0$ 为船在左侧。就可以通过两种情况进行分类讨论。

当 $z=1$ 时,有以下几种情况:

  • 两个道士到达左岸
  • 一个道士一个野人到达左岸
  • 一个道士到达左岸
  • 一个野人到达左岸
  • 两个野人到达左岸。

当 $z=2$ 时的情况与上文相近,只是从左岸到达右岸。

分析完毕后,我们可以得到以下的转移数组:

int dx[10] =  {-1, -1, -2, 0, 0, 1, 1, 2, 0, 0};
int dy[10] =  {-1, 0, 0, -1, -2, 1, 0, 0, 2, 1};

其中 $0-5$ 号元素代表着船在右岸的情况,剩余的元素代表船在左岸的情况。在转移的时候要判断状态的合法性,切记如果某一时刻道士的人数为 $0$ 野人是无法攻击道士的。

因为题目要求需要输出合法的方案,故在广搜的时候我们需要通过链表记录一下这个状态的上一个转台,最后从最后的状态开始,倒序输出。倒序输出可以通过栈来实现,这里不做过多的讲解。

参考代码

#include <bits/stdc++.h>
using namespace std;

int dx[10] =  {-1, -1, -2, 0, 0, 1, 1, 2, 0, 0};
int dy[10] =  {-1, 0, 0, -1, -2, 1, 0, 0, 2, 1};
int used[5][5][5];
int n = 3;
map<pair<int, pair<int, int>>, pair<int, pair<int, int>>> ans;

void out() {
    stack<pair<int, pair<int, int>>> tmp;
    pair<int, pair<int, int>> it =  make_pair(0, make_pair(0, 0)), ed = make_pair(3, make_pair(3, 1));
    do{
        tmp.push(it);
        it = ans[it];
    }while(it != ed);
//  cout << it.first << " " << it.second.first << " " << it.second.second << "\n";
    tmp.push(it);
    while(!tmp.empty()) cout << tmp.top().first << " " << tmp.top().second.first << " " << tmp.top().second.second << "\n", tmp.pop();
    exit(0);
}

void bfs() {
    queue<pair<int, pair<int, int>>> q;

    q.push(make_pair(3, make_pair(3, 1)));
    while(!q.empty()) {
        if(q.front() == make_pair(0, make_pair(0, 0)))  {
            out();
            return ;
        }
        int x = q.front().first, y = q.front().second.first; 
        if(q.front().second.second) {
            for(int i = 0; i < 5; i++) {
                int nx = x + dx[i], ny = y + dy[i];
                if((nx < ny && nx != 0) || (n - nx < n - ny && nx != 3)|| used[nx][ny][0] != 0|| nx < 0 || ny < 0|| nx > n || ny > n) continue;
                used[nx][ny][0] = 1;
                q.push(make_pair(nx, make_pair(ny, 0)));
                ans[make_pair(nx, make_pair(ny, 0))] = make_pair(x, make_pair(y, 1));
            }
        }
        else {
            for(int i = 5; i < 10; i++) {
                int nx = x + dx[i], ny = y + dy[i];
                if((nx < ny && nx != 0) || (n - nx < n - ny && nx != 3)||used[nx][ny][1] != 0|| nx < 0 || ny < 0|| nx > n || ny > n) continue;
                used[nx][ny][1] = 1;
                q.push(make_pair(nx, make_pair(ny, 1)));
                ans[make_pair(nx, make_pair(ny, 1))] = make_pair(x, make_pair(y, 0));
            }
        }
        q.pop();
    }
} 

int main() {
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
//  freopen("AKIOI.in", "r", stdin);
//  freopen("AKIOI.out", "w", stdout);
    bfs();
    return 0;
}
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇