猴子選大王(3種超簡單的方法)
阿新 • • 發佈:2019-01-09
17個猴子圍成一圈,從某個開始報數1-2-3-1-2-3-……報“3”的猴子就被淘汰,遊戲一直進行到圈內只剩一隻猴子它就是猴大王了。
方法一:
小技巧:用陣列來記錄猴子是否在圈內的狀態:在圈內記為“1”,不在圈內記為“0”。並以累加陣列元素值來模擬報數過程,這樣就減少了判斷猴子是否在圈內的操作。
C++程式碼如下:
#include <iostream>
#include <vector>
using namespace std;
const int N = 17;
//列印N只猴子的狀態(“1”表示在圈內,“0”表示不在圈內)
void printVec(const vector<int> &v)
{
for (vector<int>::const_iterator it = v.begin();it != v.end();++it)
{
cout<<*it<<' ';
}
cout<<endl;
}
int monkeyKing(vector<int> v)
{
//n記錄還有多少隻猴子在圈內
int n = N;
int k = 0;
int i;
while (n > 1)
{
for (i=0;i<N;++i)
{
k += v[i];
if (k == 3)
{
v[i] = 0;
printVec(v);
k = 0;
--n;
}
}
}
//最後一隻猴子下標為1
for (int i=0;i<N;++i)
{
if (1 == v[i])
return i+1;
}
}
int main()
{
vector<int> v(N,1);
cout<<"猴大王是第"<<monkeyKing(v)<<"只."<<endl;
return 0;
}
執行結果:
方法二:
方法一的缺點是每次都要掃描包括已出圈的所有猴子,時間效率比較低。而如果用陣列元素來儲存其下一隻在圈內猴子的下標,就能方便地找到下一隻在圈內猴子。當一個猴子的下一隻猴子就是自己時,圈內就只剩一隻猴子,它就是候大王了。
C++程式碼:
#include <iostream>
#include <vector>
using namespace std;
const int N = 17;
int main()
{
vector<int> v(N,0);
for (int i=0;i<N-1;++i)
{
v[i] = i+1;
}
int test = 0;
int last;
while(test != v[test])
{
for (int i=0;i<3;++i)
{
last = v[test];
test = v[last];
cout<<"第"<<test+1<<"只猴子報3"<<endl;
v[last] = v[test];
test = v[test];
}
}
cout<<"猴大王是第"<<test+1<<"只."<<endl;
return 0;
}
執行結果:
updata 2016.07.16
方法3:
在n(0、1、2、3、……、n-1)只猴子中,假定報數m的猴子被刪除,則第一隻被刪除的猴子編號為(m-1)%n,記為k,那麼刪除k之後剩下的n-1只猴子為0、1、……、k-1、k+1、……、n-1,並且下一次是從k+1開始計數。相當於在剩下的序列種,k+1排在最前面,從而形成k+1、……、n-1、0、1、……、k-1。接下來將剩下的這n-1個數字的序列k+1、……、n-1、0、1、……、k-1對映形成一個從0到n-2的序列0、1、2、……、n-2。把對映定義為p,則p(x)=(x-k-1)%n。逆過來0、1、2、……、n-2對映為k+1、……、n-1、0、1、……、k-1,時則p’(x)=(x+k+1)%n,而k=(m-1)%n,故p’(x)=(x+m)%n。最後一隻猴子的編號為0,故x=0,n=1。例如當m=3時,p’(0)=(0+3)%1=3,表示最後一隻猴大王在倒數第二輪(編號也是從0開始)中編號為3。
下面給出C++程式碼:
#include <iostream>
using namespace std;
//n只猴子,報數m的被刪掉
int LastRemaining(unsigned int n, unsigned int m)
{
if (n<1 || m<1) return -1;
//last表示最後一隻猴子(猴大王)在每輪(先倒數第1輪,再求倒數第二輪,...)中自己的序號
//倒數第一輪時只有一隻猴子(猴大王),編號為0
int last = 0;
//i表示倒數第i次排序
for (int i=2;i<=n;++i)
{
last = (last+m)%i;
}
return last+1;//+1為符合習慣,表示將編號變成從1開始
}
int main()
{
cout<<LastRemaining(17, 3)<<endl;
return 0;
}