1. 程式人生 > >嗶哩嗶哩2019.9.21筆試題——扭蛋機(堆的思想解決)

嗶哩嗶哩2019.9.21筆試題——扭蛋機(堆的思想解決)

一、題目:扭蛋機 甲乙倆人剛開始都沒有蛋,甲扭2號機,乙扭3號機。 (1)扭蛋機的規則: 2號扭蛋機:2x+1 3號扭蛋機:2x+2 eg: 如果甲剛開始沒有蛋,扭一下2號機,獲得2*0+1=1顆蛋。 (2)遊戲規則: 要求以最少的次數恰好扭出N個蛋。 (3)扭蛋規則: 甲乙倆人部分先後,一人扭完蛋將所有的蛋交由另一個人扭或者自己扭,但是要保證扭蛋次數最少,且恰好扭出N個蛋。

(4)輸入輸出: 輸入:需要扭出的N個蛋。 輸出:依次使用扭蛋機的編號。 (5)eg: 輸入: 10 輸出: 233

二、思路: 1、將扭蛋的題目轉化為在堆中查詢某一節點:從堆頂到該節點的路徑。 看到扭蛋機的規則中的2x+1、2

x+2。 想到用堆:2x+1為左孩子,2x+2為右孩子,父親為x。 且無需建堆操作: 因為 0~N,既是下標,也是陣列中的儲存元素。 所以,遍歷陣列時,直接取對應下標即可,無需弄一個數組專門存放堆中元素。 在這裡插入圖片描述 eg:要扭到10個蛋,必須走0->1->4->10這一條路,且堆的高度最小。

2、在堆中查詢某一節點:從堆頂到該節點的路徑。 從該節點開始,一路向上查詢父節點,直至遇到堆頂元素為止,將遇到的父節點按時間先後順序依次儲存在棧中,最後,將棧中元素逆序輸出即可。

	int k;
	cin>>k;//恰好扭出k個蛋
	stack<int> s;
	s.push(k);
	while (((k - 1) / 2) > 0){
		k = (k - 1) / 2;
		s.push(k);
	}

	while (!s.empty()){
		int x = s.top();
		s.pop();
		cout << x << " ";
	}

最後,對棧中輸出的元素進行數值判斷,如果是左孩子,輸出2,如果是右孩子輸出3。 這樣就滿足題目要求啦!!

三、程式碼如下:

#include<iostream>
#include<stack>
using namespace std;
//扭蛋機
int main(){
	int k;
	cin >> k;//恰好扭出k個蛋
	stack<int> s;
	s.push(k);
	while (((k - 1) / 2) > 0){
		k = (k - 1) / 2;
		s.push(k);
	}

	while (!s.empty()){
		int x = s.top();
		s.pop();
	//	cout << x << " ";
		if (x % 2)cout << 2;
		else cout << 3;
	}
	cout << endl;
}

測試了10組資料: 在這裡插入圖片描述