一、題目大意
題目鏈接:https://pintia.cn/problem-sets/988034414048743424/problems/988036815555948544
P 個海盜偷了 D 顆鑽石后來到公海分贓,一致同意如下分贓策略:
首先,P 個海盜通過抽簽決定 1 - P 的序號。然后由第 1 號海盜提出一個分配方案(方案應給出每個海盜分得的具體數量),如果能夠得到包括 1 號在內的絕對多數(即大於半數)同意,則按照該分配方案執行,否則 1 號將被投入大海喂鯊魚;而后依次類似地由第 2 號、第 3 號等等海盜提出方案,直到能夠獲得絕對多數同意的方案出現為止,或者只剩下最后一位海盜,其獨占所有鑽石。請編寫一個程序,給出第 1 號海盜的鑽石分配方案中自己分得的鑽石數量。
附帶的三個假定:
- “聰明”與“貪婪”假定:每個海盜總能夠以本人利益最大化作為行為准則;
- “人性化”假定:在能夠取得盡量多鑽石的情況下,海盜不會故意致同伙於死地;
- “無偏見”假定:海盜之間沒有個人恩怨,分給其他海盜鑽石的次序以小序號優先為原則。
輸入格式:
輸入在一行中給出 2 個正整數 D 和 P(3≤P≤D≤100)。
輸出格式:
輸出第 1 號海盜的鑽石分配方案中自己分得的鑽石數量。
輸入樣例:
10 7
輸出樣例:
6
二、解題思路
https://www.cnblogs.com/AndyJee/p/4613708.html
具體參考這位大佬寫的思路,本人簡單談談自己對於大佬博客的理解
以本題樣例舉例,我將大佬列出來的表進行了左右翻轉
2人:(10,0)
3人:(0,1,9)
4人:(1,2,0,7)
5人:(2,0,1,0,7)
6人:(0,1,2,1,0,6)
7人:(1,0,0,2,1,0,6)
我們假設從左到右依次為1~n號。
現在來具體的模擬每一遍的過程。
2人:(10,0)
此時,來了第三個人,三個人一共需要兩個人(加上他自己)才能過通過方案,因此他只需要一個人聽他的話(至少被分到一塊金塊)
為了偷懶,三號決定在上一個人的方案上做出修改
三號對一號說:你太貪婪了,不能拿這么多,作為懲罰我不給你金塊了
三號對二號說:我決定給你一塊金塊,投票的時候你懂我意思吧
最后,剩下的金塊被三號自己拿走了
於是三號的方案就出來了:(0,1,9)
3人:(0,1,9)
同上,四號來了,此時一共四個人,需要三個人(包括他自己)才能通過方案,因此他只需要兩個人聽他的話(至少被分到一塊金塊)
同樣,他看了三號的方案,決定做一些修改
四號對一號說:和我混吧,我看你比較可憐,決定給你一塊金塊
四號對二號說:我覺得你表現不錯,給你多加一塊金塊
四號一看,自己的小弟已經夠了,於是對剩下的人說:你們走吧,留你們一條小命,剩下的金子我自己拿走了
於是四號的方案就出來了:(1,2,0,7)
4人:(1,2,0,7)
同上,五號來了,需要三個人(包括他自己),因此還需要兩個小弟
五號對一號說:我覺得你表現不錯,加一塊金塊
五號對二號說:我覺得你太貪婪了,要的太多了,作為懲罰不給你了
五號對三號說:跟我吧,給你一塊
五號一看小弟夠了,於是對剩下的人說:你們走吧,留你們一條小命,剩下的金子我自己拿走了
於是五號的方案:(2,0,1,0,7)
………………
以此類推
以我的理解,需要在上一個人的方案上進行給每個人加金塊是為了能說服他們投自己的方案,這樣更方便理解
這里我設置的界線是2個金塊,畢竟花三個金塊收買一個人太貴了
三、ac代碼
#include<bits/stdc++.h> using namespace std; int main(void) { vector<int>vec; int d,p; scanf("%d %d",&d,&p); vec.push_back(d); vec.push_back(0); while (vec.size()<=p) { int cnt=0; for (auto &it:vec){ if (it>=2) it=0; else it++; if (it) cnt+=it; if (cnt+1>p/2) break; } vec.push_back(d-cnt); } printf("%d",vec[vec.size()-1]); return 0; }
當時以上只是我根據那位大佬題解的猜想,便於理解
在寫這篇題解的時候也冒出了一些疑問
感覺自己更多是運氣好猜對了才ac
希望有大佬能指出我的問題,感激不盡
peace