1. 程式人生 > >商人過河問題(n個)-Matlab

商人過河問題(n個)-Matlab

n個商人過河問題

Description

        商人過河問題:n名商人各帶一名隨從過河,一隻小船隻能容納z個人,隨從們約定,只要在河的任何一岸,一旦隨從人數多於商人人數就殺人越貨,但是商人們知道了他們的約定,並且如何過河的大權掌握在商人們手中,商人們該採取怎樣的策略才能安全過河並且渡河次數最少呢??

Explaination

  1. 先從一般的例子開始討論,通過3名商人各帶一名隨從過河,一隻小船隻能容納3個人,從此岸的角度確定安全矩陣。再遞推,確定n名商人各帶一名隨從過河,一隻小船隻能容納z個人的安全狀態矩陣(0、1)的規律
  2. 然後分類討論,設立判定條件,來討論什麼情況下不存在安全過河狀態以及對安全矩陣的遍歷,通過設定單元陣列來儲存渡河所有過程,以便於後續查詢和判斷
  3. 最後通過判斷此岸商人、僕人是否都已經到達彼岸來選擇出最少渡河次數,並輸出一組結果;如果不存在安全到達的情況則輸出No answer!

Example

  • 當n=3,z=3時,渡河的最少次數、此岸的商人數和僕人數變化如下:
  • k =
    
         5
    
    W =
    
         3     3
         3     1
         3     2
         0     2
         0     3
         0     0
  • 當n=5,z=3時,渡河的最少次數、此岸的商人數和僕人數變化如下:
    k =
    
             11
    
    W =
    
              5     5
              5     3
              5     4
              5     1
              5     2
              2     2
              3     3
              0     3
              0     4
              0     2
              0     3
              0     0

Code

:對於不同情況的m、z只需要修改程式碼中的m、z即可。

% Matlab
clear;
home;
m=3; %商人、僕人數
z=3; %船上可載人數

m=m+1; %矩陣中不存在0位置
A=zeros(m); %列表示商人,行表示僕人
for i=0:m-1 %尋找安全狀態,1為安全,0為不安全
    for j=0:m-1
        if (i==j)||(i==m-1)||(i==0)
            A(i+1,j+1)=1;
        end
    end
end
s={}; %用來存放路徑
p=1;  %用來表示放在每一行的第幾列
R=[]; %特殊情況
s{1,1}=[m,m,1]; %[a,b,c]a表示此岸商人數,b表示此岸僕人數,c表示由上面情況c推的

for t=1:100 %迴圈上界適當
    flag=0; %用來判斷是否重複
    trump=0; %用來判斷是否已經存在可安全渡河的情況
    k=t; %k表示渡河次數
    if z>=2*(m-1) %當船載人數大於或等於總人數
        k=1 
        R=[m-1,m-1;0,0]
        break;
    end 
    
    for a=1:sum(~cellfun(@isempty, s(k,:))) %表示有幾種情況(相對於同一個k來說)
        if a==1 %第一種情況,從第一個列開始存
            p=1;
        end
        n1=s{k,a}(1,1); %賦值,商人數
        n2=s{k,a}(1,2); %賦值,僕人數
        
        for i=0:z %渡河
            for j=0:z
                if (i+j>=1 && i+j<=z) && (n1+i*(-1)^k<=m && n1+i*(-1)^k>=1) && (n2+j*(-1)^k<=m && n2+j*(-1)^k>=1) && (A(n1+i*(-1)^k,n2+j*(-1)^k)==1)
                %條件判斷
                    if k>=2 %判斷是否重複
                        for e=1:sum(~cellfun(@isempty, s(k-1,:)))
                            if (s{k-1,e}(1,1)==n1+i*(-1)^k) && (s{k-1,e}(1,2)==n2+j*(-1)^k)
                                flag=1; %如果發現重複,則flag==1
                                break;
                            end
                        end
                    end
                    if flag==0 %不重複存入
                        s{k+1,p}=[n1+i*(-1)^k,n2+j*(-1)^k,a];
                        p=p+1;
                    end
                    flag=0; %每一次判斷之後flag都要歸0
                end
            end
        end
    end
    
    k=k+1; %一次考慮完後k+1
    s{k+1,1}=[]; %往下建立空cell
    if sum(~cellfun(@isempty, s(k,:)))==0 %判斷是否有新的情況生成,0表示s{k,:}全部為空
        'No answer!'
        break;
    end
    
    for win=1:sum(~cellfun(@isempty, s(k,:))) %判斷是否已有完成任務的情況
        if s{k,win}(1,1)==1 && s{k,win}(1,2)==1
            trump=1;
            break;
        end
    end
    if trump==1
        k=k-1
        break;
    end
end

if trump==1  %輸出一組結果
    W=[];
    qq=win;
    for oo=1:k+1
        W(oo,1)=s{k+2-oo,qq}(1,1)-1;
        W(oo,2)=s{k+2-oo,qq}(1,2)-1;
        qq=s{k+2-oo,qq}(1,3);
    end
    W=flipud(W)
end


<第一次寫部落格>ヽ(○^㉨^)ノ♪ 

相關推薦

商人問題(n)-Matlab

n個商人過河問題 Description         商人過河問題:n名商人各帶一名隨從過河,一隻小船隻能容納z個人,隨從們約定,只要在河的任何一岸,一旦隨從人數多於商人人數就殺人越貨,但是商人們知道了他們的約定,並且如何過河的大權掌握在商人們手中,商人們該採取怎樣的

商人問題的Python實現

# -*- coding: cp936 -*- #定義允許存在的狀態集合 def allowexistset(): merchants=int(raw_input("請輸入商人數: ")) slivers=int(raw_input("請輸入隨從數: ")) allowset

商人問題(DFS)

問題描述: 3個商人帶著3個僕人過河,過河的工具只有一艘小船,只能同時載兩個人過河,包括划船的人。在河的任何一邊,只要僕人的數量超過商人的數量,僕人就會聯合起來將商人殺死並搶奪其財物,問商人應如何設計過河順序才能讓所有人都安全地過到河的另一邊。 詳細過程參見《數學模型》第四

商人 決策

這是上數模老師講的一道題,解法有圖解法和遞迴窮舉的方式,這裡我採用後者。 詳細說明可以參考:http://www.docin.com/p-970116457.html 程式碼: #include<cstdio> #include<cstring> #

爸爸 媽媽 獵人和狗 有兩男孩 兩女孩 。他們要,但獵人不在的時候,狗咬任何人,當爸爸不在的時候,媽媽打小男孩,媽媽不在的時候,爸爸打小女孩,他們怎麼過去

爸爸 媽媽 獵人和狗 有兩男孩 兩個女孩 。他們要過河,但獵人不在的時候,狗咬任何人,當爸爸不在的時候,媽媽打小男孩,媽媽不在的時候,爸爸打小女孩,他們怎麼過去 有一天看到的一個網上題目,一時興起便寫了一下,o(^▽^)o #include<stdio.h>

Linux awk統計日誌中出現的IP(或出現次數最多的NIP)

awk是一個強大的文字分析工具,相對於grep的查詢,sed的編輯,awk在其對資料分析並生成報告時,顯得尤為強大。簡單來說awk就是把檔案逐行的讀入,以空格為預設分隔符將每行切片,切開的部分再進行各種分析處理。 awk的用法 awk 'BEGIN{ commands }

Java從檔案中跳n位元組讀取資料

下面例項是跳過前10個位元組,從第11個位元組開始讀取File file = new File("tcp.txt"); FileInputStream stream = new java.io.FileInputStream(file);

[數學模型]商人怎樣安全

問題描述 三名商人各帶一個隨從乘船渡河,一隻小船隻能容納兩人,由於他們自己划行,隨從密約,在和的任一岸,一旦隨從的人數比商人多,就殺人越貨,但是如何安排乘船的大權安排在商人們的手中,商人們怎樣才能安全渡河? 模型假設 我們需要對問題做一些假設:

問題 貪心

開始 難度 pac map sca 的人 names 最優 sort 過河問題 時間限制:1000 ms | 內存限制:65535 KB 難度:5 描述 在漆黑的夜裏,N位旅行者來到了一座狹窄而且沒有護欄的橋邊。如果不借助手電筒的話,大家是無論如何也不敢過橋去的

luogu P1809 問題_NOI導刊2011提高(01)

-m iostream style 人才 三次 nbsp code mat 問題 題目描述 有一個大晴天,Oliver與同學們一共N人出遊,他們走到一條河的東岸邊,想要過河到西岸。而東岸邊有一條小船。 船太小了,一次只能乘坐兩人。每個人都有一個渡河時間T,船劃到對

【DP】青蛙

現在 div col 接受 printf mic ive 開始 可能 Description   在河上有一座獨木橋,一只青蛙想沿著獨木橋從河的一側跳到另一側。在橋上有一些石子,青蛙很討厭踩在這些石子上。由於橋的長度和青蛙一次跳過的距離都是正整數,我們可以把獨木橋上青蛙

n括號對的所有可能情況

括號 main color 思路 出棧 gin col r+ div 所有可能情況的數量為卡特蘭數。故求所有可能的出棧情況與此類似。 思路: 若左括號沒全插入,則插入左括號; 若已插入左括號數比已插入右括號數多,則插入右括號; 1 #include<st

這些Linux數據恢復工具,你用哪幾

linux數據恢復不論你運用的是臺式電腦仍是筆記本,需求重視的要點之一都是怎麽保護好你的名貴數據。由於總會有各種突發狀況使你的系統潰散,然後你要做的就是恢復數據。不論你怎麽想,要是我失去了一切的數據卻無法恢復的話,我會分分鐘肢解了這臺破電腦。不過幸虧的是,如今商場上有不少的數據恢復工具,能協助咱們從體系的硬盤

luogu P1002

for clas tro ret iostream article 表示 格式 strong 題目描述 棋盤上A點有一個過河卒,需要走到目標B點。卒行走的規則:可以向下、或者向右。同時在棋盤上C點有一個對方的馬,該馬所在的點和所有跳躍一步可達的點稱為對方馬的控制點。因

歐幾裏得算法以及擴展歐幾裏得算法(noip2005提高組第二題)

font 以及 family nbsp 最大公約數 這樣的 noi 其他 sun 歐幾裏得算法:也被稱作輾轉相除法 gcd(a,b)=gcd(b,a%b); 終止條件a=gcd b=0; (gcd為a,b的最大公約數) 擴展歐幾裏得算法: a 和 b 的最大公約數是 g

codevs 1245 最小的N

pan width 長度 spa dev char getc 初始 turn 題目描述 Description 有兩個長度為 N 的序列 A 和 B,在 A 和 B 中各任取一個數可以得到 N^2 個和,求這N^2 個和中最小的 N個。 輸入描述 Input

《劍指offer》 面試題43 n骰子的點數 (java)

r+ nal ret 次循環 分而治之 源碼 ava 面試 ble 引言:寫這篇文章的初衷只是想做個筆記,因為這道題代碼量有點大,有點抽象,而書上並沒有詳細的註釋。為了加深印象和便於下次復習,做個記錄。 原題:把n個骰子扔到地上,所有骰子朝上一面的點數之後為s. 輸入n,打

cnblogs https ring string end lan tar stream alt 鏈接 分析:當前點的情況僅由其左邊和上邊的點決定,然後馬會走過的點標記一下即可 1 #include "iostream" 2 #include "cstdio" 3

(hdu step 7.1.6)最大三角形(凸包的應用——在n點中找到3點,它們所形成的三角形面積最大)

三角形 struct names com 都在 acm sni 都是 tran 題目:最大三角形Time Limit: 5000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total S