一、题目大意
题目链接: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