經濟學上有個“海盜分金”模型:是說5個海盜搶得100枚金幣,他們按抽籤的順序依次提方案:首先由1號提出分配方案,然後5人表決,投票要超過半數同意方案才被通過,否則他將被扔入大海喂鯊魚,依此類推。
假定“每個海盜都是絕頂聰明且很理智”,那麼“第一個海盜提出怎樣的分配方案才能夠使自己的收益最大化?”
推理過程是這樣的
1.如果只剩兩個海盜 那麼海盜4無論提什麼,海盜5都會否決.
2.所以海盜3 可以提出 100 ,0,0的方案(這裏假設海盜1,2如果入水了)
3.海盜2 要拉攏兩個人才能通過方案,只要放棄3號給4,5兩人1人1個金幣就好了(98,0,1,1)
4.海盜1 也要拉攏人,那麼需要在海盜2的基礎上加碼,放棄海盜2(97,0,1,2,0)
那如果6個海盜呢,7個海盜呢
以下是算法思路
1.海盜n要爭取除自己外n/2的人同意
2.分配按保守來(海盜n,拉攏n/2個人,並且提出的分配方案比他之前的更加有誘惑力 )
比如 海盜n-1到海盜1提出的方案裏,能給他拉攏的人最多x個金幣,海盜n就給他x+1個
這個典型的就是動態規劃問題
3.dp去記錄每個海盜的分配方案中 除分配人以外每個人能獲得的最大值
比如4個海盜的時候的dp=[0,1,1](第一個0代表第三個人被放棄了,按照推理每個海盜都會放棄他前一個人)
那麼5個海盜就從中取出5/2=2個最小的值,分別給他們都加1個金幣 (5選擇拉攏成本較小的4,和3)結果就是 dp=[0,1,2,1]
6個就是[0,1,2,2,2](注意dp是前面方案裏的最大值,所以把海盜n要拉攏的對象+1,其他保持不變)
以下是代碼實現
public class Coin {
//n>3
public List<List<Integer>> solution(int n,int coin) {
List<List<Integer>> results=new ArrayList<>();
List<Integer> ret=new ArrayList<>(4);
Collections.addAll(ret,98,0,1,1);
results.add(ret);
List<Integer> dp=new LinkedList<>();
Collections.addAll(dp,0,1,1);
for (int i = 5; i <= n; i++) {
List<Integer> retNow=new ArrayList<>(i);
//初始化
for (int i1 = 0; i1 < i; i1++) {
retNow.add(0);
}
//除自己外需要支持的海盜數
int num = i / 2;
//找出需要金幣最小的幾個海盜
Set<Integer> set=new HashSet<>();
int sum = 0;
while (--num>=0){
int min=Integer.MAX_VALUE;
int index=0;
for (int j = 0; j < dp.size(); j++) {
if(min>dp.get(j)&&!set.contains(j)){
min=dp.get(j);
index=j;
}
}
set.add(index);
min=min+1;
sum+= min;
dp.set(index,min);
retNow.set(index+2,min);
}
dp.add(0,0);
if(coin-sum<0)
break;
retNow.set(0,coin-sum);
results.add(retNow);
}
return results;
}
public static void main(String[] args) {
List<List<Integer>> list=new Coin().solution(100,100);
for (int i = 0; i < list.size(); i++) {
System.out.println(list.get(i));
}
}
}
分配結果如下
[98, 0, 1, 1]
[97, 0, 1, 2, 0]
[95, 0, 1, 2, 0, 2]
[94, 0, 1, 2, 3, 0, 0]
[91, 0, 1, 2, 3, 0, 3, 0]
[91, 0, 1, 2, 3, 0, 0, 0, 3]
[86, 0, 1, 2, 3, 4, 4, 0, 0, 0]
[86, 0, 1, 2, 3, 4, 0, 0, 4, 0, 0]
[82, 0, 1, 2, 3, 4, 0, 0, 0, 0, 4, 4]
[80, 0, 1, 2, 3, 4, 5, 5, 0, 0, 0, 0, 0]
[75, 0, 1, 2, 3, 4, 5, 0, 0, 5, 5, 0, 0, 0]
[75, 0, 1, 2, 3, 4, 5, 0, 0, 0, 0, 0, 5, 5, 0]
[68, 0, 1, 2, 3, 4, 5, 6, 6, 0, 0, 0, 0, 0, 0, 5]
[67, 0, 1, 2, 3, 4, 5, 6, 0, 0, 6, 6, 0, 0, 0, 0, 0]
[61, 0, 1, 2, 3, 4, 5, 6, 0, 0, 0, 0, 0, 6, 6, 6, 0, 0]
[60, 0, 1, 2, 3, 4, 5, 6, 7, 0, 0, 0, 0, 0, 0, 0, 0, 6, 6]
[51, 0, 1, 2, 3, 4, 5, 6, 7, 0, 7, 7, 7, 0, 0, 0, 0, 0, 0, 0]
[51, 0, 1, 2, 3, 4, 5, 6, 7, 0, 0, 0, 0, 0, 7, 7, 7, 0, 0, 0, 0]
[44, 0, 1, 2, 3, 4, 5, 6, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 7, 7, 7]
[40, 0, 1, 2, 3, 4, 5, 6, 7, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[32, 0, 1, 2, 3, 4, 5, 6, 7, 8, 0, 0, 0, 0, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0]
[32, 0, 1, 2, 3, 4, 5, 6, 7, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 8, 8, 8, 0, 0]
[21, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 8]
[19, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[10, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 0, 0, 0, 0]
[9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9]
即興寫的,如果有疏漏請多多包涵