資料結構機試複習2 賽馬 猴子選大王

2021-08-14 09:05:04 字數 3725 閱讀 1396

ex1:賽馬

a與b之間將進行一場賽馬比賽,c為裁判。a與b分別擁有n匹馬,這2n匹馬中每匹馬擁有的能力值都不相同。比賽前,參賽的兩人先決定自己的馬的出場順序;比賽時,a的第一匹馬將對戰b的第一匹馬,a的第二匹馬將對戰b的第二匹馬,以此類推。在每一輪的比賽當中,能力值較高的馬將獲得勝利,並記其擁有者加1分。進行過n輪比賽之後,得分較高的人將獲得最終的勝利,並贏得所有的馬。當然,可能存在平局的情況,此時算作裁判c勝利,並獲得所有的馬。

問:給定每一匹馬的能力值,裁判c能否通過重新調整馬匹參賽順序而獲得勝利?

第一行輸入乙個整數n,1<=n<=100。

第二行輸入n個整數,代表選手a所有馬匹的能力值。

第二行輸入n個整數,代表選手b所有馬匹的能力值。

如果可以平局的話,則輸出「yes」,否則輸出「no」。 4

1 2 7 8

3 4 5 6

21 2

3 4

yesno

#include//#include不確定考試是否可以使用sort()函式  

#includeusing namespace std;

//若不可以使用sort(),自行定義快速排序函式,參考嚴蔚敏《資料結構c語言版》

int partition(int list, int low, int high)

list[low] = pivotkey;

return low;

}

void qsort(int list, int low, int high)

return;

}

int main()

j++;

} j = 1; //這一部分與上一部分作用相同

for (int i = n / 2 + 1; i <= n; i++)

j++;

} if (flag) ans = "yes";

} cout << ans << endl;

} return 0;

}

思路:貪心演算法

首先,因為每匹馬的能力值均不相同,所以如果n為奇數,必然兩人勝利的次數不可能相等,直接輸出「no」;

若n為偶數,輸入兩組數,並由小到大排列。

如果題目要求不可以使用自帶的sort()函式,則需要自己排序,這裡採用的是快速排序方法。

然後將兩組數分別分成前、後兩部分,

先後逐一比較a的前半部分和b的後半部分,b的前半部分和a的後半部分

只要出現前半部分的數比後半部分的數大的情況,就表示無法滿足要求

否則,可以達到要求。

ex2:猴子選大王

猴子選大王,有n只猴子,從1~n進行編號。它們按照編號的順時針方向,排成乙個圓圈,然後從第一只猴子開始報數。第一只猴子報1,以後每只猴子報的數字都是它前面猴子所報數字加1。如果乙隻猴子報的數字是m,則該猴子出列,下乙隻猴子重新從1開始報數。剩下的猴子繼續排成乙個圓圈報數,直到全部的猴子都出列為止。最後乙個出列的猴子勝出。

第一行為乙個整數t,表示測試的例子數量。接下來會有t行輸入,每一行包含兩個正整數n(0對於每個測試例子,輸出猴子大王的編號。

25 2

4 33

1如果從數學角度思考這道題,答案非常簡單。

先給出**

#includeusing namespace std;

int main(){

int t,n,m;

cin>>t;

while(t--){

while(cin>>n>>m){

int king=0;

for(int i=2;i<=n;i++)

king=(king+m)%i;

cout<

首先,我們定義乙個函式 f(n,m),n和m的含義與題中相同,函式值表示勝利者的位置(陣列下標)。

接下來,我們要證明

f(n,m)=[ f(n-1,m)+ m ] %m       (*)

假設給出一組數: 1,2,3,4,5,6,7; n=7,m=3

我們觀察一下整個過程

1)從1開始報數, 3出列, 陣列變為1,2,x,4,5,6,7

2)從4開始報數,6出列,陣列變為1,2,x,4,5,x,7

3)從7開始報數,2出列,陣列變為1,x,x,4,5,x,7

4)從4開始報數,7出列,陣列變為1,x,x,4,5,x,x

5)從1開始報數,5出列,陣列變為1,x,x,4,x,x,x

6)從1開始報數,1出列,陣列變為x,x,x,4,x,x,x

4為最終的勝利者

其實,這個陣列很像乙個迴圈佇列。如果我們在每一輪,都把第1個報數的人的序號定為0,第2個報數的定為1,……,第i個報數的定為i-1,可以得到如下**:紅色為每一輪出列的數字,紫色為最終的勝利者,藍色部分是已經在前面出現過的數字,目的是為了將隊伍「補齊」序號0

1234

56第一輪123

456

7第二輪

456

7124

第三輪712

4571

第四輪457

1457

第五輪145

1451

第六輪141

4141

第七輪4

勝利者4,在最後一輪中的位置是0, 也就是 f(1,3)=0,那麼他在第六輪中的位置在哪呢?

按照公式我們有 f(2,3)=[ f(1,3)+3 ] % 2=3 %2 =1,對照表,果然如此!

那麼這是為什麼呢?

其實每當一輪報數報到m,在m出列後,相當於整個陣列向前移動了m 位(我們可以想象這是一條縱隊,每個人報出自己的數,如果他是m,就出列;否則就排到隊伍末尾去;這樣,還沒有報數的人就整體前進了m位)。

那麼反過來,已經知道勝利者在n個人的時候所站的位置,那麼他在上一輪中,站的位置就應當是這一輪的位置後移m位。

即 f(n+1,m)=f(n,m)+m,這樣我們已經理解了(*)這個公式的一半。

那麼為什麼還要再對n取模呢?

仍然看上述例子,如果不對n取模,那麼勝利者4在第六輪中的位置應當是0+3=3,然而事實上,在第六輪中僅僅只有兩個人(位置為0~1),將勝利者的位置記為3顯然是不合理的。我們已經將這個過程理解為迴圈佇列,那麼我們試著將整個隊伍「補齊」,也就是僅剩的兩人重複排隊,1,4,1,4,1,4,……, 顯然這是乙個迴圈的過程,同乙個數字所在的不同位置是對n取模同餘的。(比如1 的位置為0,2,4,……;4的位置為1,3,5,……)因此,我們將「越界」的位置模n,就得到了真實的位置。

也就是說,取模,是為了解決下標越界的問題!

現在我們再來看一下**的核心部分,是不是就很好理解了呢?

int king=0;

for(int i=2;i<=n;i++)

king=(king+m)%i;

cout<

因為最終的勝利者在最後一輪(1人)的位置(陣列下標)必然為f(1,m)=0,

則他在倒數第二輪(

2人)的位置為 f(2,m)=(f(1,m)+m)%2,

倒數第三輪(

3人)位置為f(3,m)=(f(2,m)+m)%3,

…… 那麼

n人的時候,他的位置就為f(n,m)=(f(n-1,m)+m)%

n。 這是乙個迭代的過程,而終止條件就是i=n。

注意我們求出來的是位置(0~n-1),而題目要求的是編號(1~n),所以最終輸出的結果還需要加上1。

資料結構機試複習10 求和 最短字首

給定乙個具有n個整數的陣列,問在s中是否存在3個元素a b c使得a b c 0。注意 三元組 a b c 必須是乙個非遞減順序 即a b c 輸出的結果不能重複 例如,給定陣列s 1 0 1 2 1 4 輸出 1,0,1 以及 1,1,2 1 先上乙個針對matrix的ac 輸入輸出沒有leetc...

機試常見的資料結構

北航的機試要求用標準c程式設計,所以很多c 的庫都沒法用。因此我使用最簡單的 實現了幾個常見的資料結構。標準c庫參考 1.陣列實現的棧。此處棧的元素預設為int,也可以改為其他。struct stack void push int x int pop bool isempty bool isfull...

機試之資料結構STL詳解

pair的常見用法詳解 algorithm標頭檔案下常用函式介紹 機試stl之stack 括號匹配 include include include include include using namespace std int main else if str i else while bracke...