• 海盗分金


      /*
      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;
    }
    
  • 相关阅读:
    订单生成案例详解
    分页案例详解
    简单的多条件查询案例
    删除选中案例详解
    转账汇款案例
    登录操作记住用户名实现
    根据自定义异常来回显错误信息
    会话技术cookie和session详解
    JDBC
    Netty入门教程——认识Netty
  • 原文地址:https://www.cnblogs.com/wzsblogs/p/4656878.html
Copyright © 2020-2023  润新知