海盗分金

  /*
  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;
}

 

posted @ 2015-07-18 14:46  伟gg  阅读(275)  评论(0编辑  收藏  举报