海盗分金-动态规划实现
经济学上有个“海盗分金”模型:是说5个海盗抢得100枚金币,他们按抽签的顺序依次提方案:首先由1号提出分配方案,然后5人表决,投票要超过半数同意方案才被通过,否则他将被扔入大海喂鲨鱼,依此类推。假定“每个海盗都是绝顶聪明且很理智”,那么“第一个海盗提出怎样的分配方案才能够使自己的收益最大化?”推理过程是这样的1.如果只剩两个海盗 那么海盗4无论提什么,海盗5都会否决.2.所以...
经济学上有个“海盗分金”模型:是说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]
即兴写的,如果有疏漏请多多包涵
更多推荐
所有评论(0)