/*
5个海盗抢到了100颗宝石,每一颗都一样的大小和价值。
他们决定这么分:
1。抽签决定自己的号码(1,2,3,4,5)
2。首先,由1号提出分配方案,然后大家5人进行表决,当且仅当半数和超过半数的人同意时,按照他的提案进行分配,否则将被扔入大海喂鲨鱼。
3。如果1号死后,再由2号提出分配方案,然后大家4人进行表决,当且仅当半数和超过半数的人同意时,按照他的提案进行分配,否则将被扔入大海喂鲨鱼。
4。以次类推......
条件:
每个海盗都是很聪明的人,都能很理智的判断得失,从而做出选择。
问题:
第一个海盗提出怎样的分配方案才能够使自己的收益最大化?
分析:从后面开始往前计算,
考虑只有两个人:无论前一个人提出什么方案,后一个人都会否决,故当有两个人的时候前一个人必死
考虑只有三个人:第一个人知道第二个必须拥护自己(否则剩下两个人时他必死),所以他可以自己独吞所有金币,分配方案 100 0 0
考虑只有四个人:由于三个人的时候没有人会面临死亡的威胁,故第一个人必须拉拢两个人,只需要在第三个人基础上选择金币最少的
两个人分别多给其一个金币即可,分配方案98 0 1 1
.
.
.
之后的情况都是依赖于前一种情况就可以决定了,用递归可以很好解决.
*/
#include <iostream>
#include <algorithm>
using namespace std;
class node
{
public:
int goal;
int pos;
node()
{
goal=pos=0;
}
};
bool cmp(node a,node b)
{
return a.goal<b.goal;
}
bool cmp2(node a,node b)
{
return a.pos<b.pos;
}
class heap
{
public:
node *p;
node *res;
int n;
heap()
{
p=NULL;
res=NULL;
n=0;
}
void copy()
{
node *tem =new node[n];
for(int i=0;i<n;i++)
tem[i]=res[i];
delete[] p;
p=tem;
}
void rebuild(int i)
{
node *temp = new node[i];
delete[] res;
res = temp;
for(int j=0;j<i;j++)
res[j].pos=j;
n=i-1;
}
void fun()
{
sort(p,p+n,cmp);
int num;
int total=100;
if(n/2.0-n/2>0)
num=n/2+1;
else
num=n/2;
for(int i=0;i<num;i++)
{
res[p[i].pos].goal+=p[i].goal+1;
total-=res[p[i].pos].goal;
}
n++;
res[n-1].goal=total;
}
void reverse()
{
for(int i=0;i<n;i++)
res[i].pos = n-res[i].pos-1;
}
void show()
{
sort(res,res+n,cmp2);
cout<<"第一个海盗分金币的方案应为:"<<endl;
for(int i=0;i<n;i++)
cout<<res[i].goal<<" ";
cout<<endl;
}
};
void dfs(int n,heap& h)
{
if(n==3)
{
h.p = new node[3];
h.res = new node[3];
h.p[0].goal=h.res[0].goal=0;
h.p[1].goal=h.res[1].goal=0;
h.p[2].goal=h.res[2].goal=100;
for(int i =0;i<3;i++)
h.p[i].pos=h.res[i].pos=i;
h.n=3;
return;
}
dfs(n-1,h);
h.copy();
h.rebuild(n);
h.fun();
}
int main()
{
int n;
cout<<"输入海盗个数:";
cin>>n;
if(n==1)
{
cout<<"第一个海盗分金币的方案应为:"<<endl;
cout<<"100"<<endl;
return 0;
}
if(n==2)
{
cout<<"第一个海盗分金币的方案应为:"<<endl;
cout<<"0 100"<<endl;
return 0;
}
heap h;
dfs(n,h);
h.reverse();
h.show();
return 0;
}