海盗分金
/* 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; }