• HDU 4023 Game(博弈)


    Game

    Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65768/65768 K (Java/Others)
    Total Submission(s): 638    Accepted Submission(s): 210


    Problem Description
    Alice and Bob are playing game with each other. They play the game on a 2D board. Alice has many vertical 1*2 tiles while Bob has many horizontal 2*1 tiles. They take turn to place their own tiles on the board. Considering about that the tiles cannot overlap each other, the player cannot do the placement any more loses. Since this is such a complex game that they could not find optimal method to play that, Alice decide to simplify this game by replace the large 2D board by some small ones. Alice set up a lot of Tetris tiles instead of the original 2D board. In the other words, the player can only place their own vertical or horizontal tiles on the Tetris-like board. Each player can choose one possible place on any Tetris tiles to place its own tiles. In fact, there are following 15 types of Tetris playground.

    The playground cannot be transformed in any ways, including reflection and rotation.
    Given the number of each type of tiles, you are asked to determine who will win the game if Alice plays first and both players are playing optimal.
     
    Input
    There are multiple test cases; the first line of input contains a single integer denoting the number of test cases.
    For each test case, there are only one line contains 15 integers denoting the number of Tetris tiles of the above 15 types. All the numbers are no greater than 100.
     
    Output
    For each test cases, output “Alice” if Alice will win the game and both player plays optimally, “Bob” otherwise.
     
    Sample Input
    3 5 4 0 0 0 0 0 0 0 0 0 0 0 0 0 5 5 0 0 0 0 0 0 0 0 0 0 0 0 0 100 100 0 0 0 0 0 0 0 0 0 2 1 0 0
     
    Sample Output
    Case #1: Alice Case #2: Bob Case #3: Alice
     
    Source
     
    Recommend
    lcy
     
     
     

    这个题目应该是一个博弈类的题目,既然是博弈,那么每一步就要为自己争取最大的利益或者为对方带来最大的损失,那么先放哪一个就要综合对自己的利益与对对方的损失来考虑。

    最后谁获得胜利只取决于Alice能走的步数是否比Bob多,同时这一因素又取决于两点:1.在双方都不能为对方带来损失时,谁是先手;2.双方还有多少个稳定的走位。

    所谓稳定的走位,就是不论对方如何走,都不会占去的但自己却随时可以走的位置。

    从上面分析的角度出发,我们可以把图分成下面5组:

    1.(1)(2)是一组,分别是Alice和Bob的稳定走位,所以可以放到最后去考虑。

    2.(15)单独为一组,综合来讲,(15)一旦放一个瓷砖,那么不仅使自己走出了一步,还能为自己留一个稳定走位,同时又能使对手失去两个位置,所以在(15)放一个瓷砖是效益最高的走法,因而双方最先都会争(15)。

    3.(3)(4)(5)(6)是一组,至于为什么这四个是一组,我们不妨从Alice的角度分析下一。如果Alice走(5)或(6),那么Alice同时可以获得一稳定走位,并让Bob失去一个位置,如果Alice走(3)(4),那么Alice可以让Bob失去两个位置,所以这两种走法对Alice的收益是相同的。反过来,对Bob而言也是一样的。既然两种走法相同,那么便于我们的统计,不妨先让Alice走(5)(6),Bob走(3)(4),直到一方走完自己的主场,然后再去瓜分剩下的(3)(4)或者(5)(6)。

    4.(7)(8)(9)(10)是一组,因为都是有一方可以牵制另一方,但另一方不能牵制这一方,具体的分析见下。

    5.(11)(12)(13)(14)是一组,为什么这样分就不说了,主要说一下双方再走完第3组之后,究竟应该先走第4组还是先走第5组。

    首先,从Alice的角度来讲,如果走(7)(8),都可以使Bob失去一个位置,走(11)(12)(13)(14)也是如此,但两种走法对Alice的收益来讲是不同的,如果Alice走(11)~(14)其中的任意一个,而Bob无论走(7)或(8)都会留一个稳定走位给Alice,而如果Alice走(7)(8)而Bob走(11)~(14)就没有这种效果了。因而Alice一定会先走(11)~(14),再走(7)(8)。同样的道理,Bob一定会先走(11)~(14),再走(9)(10)。

    至于(7)(8)(9)(10)的瓜分,从Alice角度来讲,走(7)(8)不仅会使自己走出了这一步,同时会使Bob失去一个位置,而Alice走(9)(10)却只能使自己走出一步罢了,并不能给Bob带来什么损失,所以Alice一定优先走(7)(8),而对于Bob来讲,他一定会先走(9)(10),最后如果(7)(8)或者(9)(10)有剩余,双方再继续瓜分。

    最后再把(1)(2)的统计加进去并看最后该谁走了即可。

    综上所述,在统计的过程中,我们要记录3个量,Alice与Bob剩余的稳定走位和走当前组的图时,该谁先走,如果图是偶数谁先谁后无所谓,但如果图是奇数,先后手的收益就会有所差别。同时,对于走同一组图,如果双方的剩余的稳定走位有相同的部分,我们可以略去这些不去统计,因为最后我们只考虑两人可走的位置数的差,所以相同的部分会抵消掉,因而就不重要了。

    #include<stdio.h>
    #include<algorithm>
    #include<iostream>
    using namespace std;
    int a[16];
    int main()
    {
       // freopen("C.in","r",stdin);
       // freopen("C.out","w",stdout);
        int T;
        int iCase=0;
        int now;//记录现在是谁走,1表示Alice ,2表示 Bob;
        int Alice,Bob;//分别是两人的保留步数
        scanf("%d",&T);
        while(T--)
        {
            iCase++;
            printf("Case #%d: ",iCase);
            for(int i=1;i<=15;i++)
              scanf("%d",&a[i]);
            Alice=Bob=0;
            now=1;//Alice先走
            if(a[15]%2==0)//先抢第15种
            {
                Alice+=a[15]/2;//加一样的可以不加的,这里便于理解
                Bob+=a[15]/2;
            }
            else
            {
                Alice+=a[15]/2+1;
                Bob+=a[15]/2;
                now=2;//Bob先走了
            }
            int tempa=a[5]+a[6];//ALice抢5,6
            int tempb=a[3]+a[4];//BOb抢3,4
            if(tempa==tempb)
            {
                Alice+=tempa;
                Bob+=tempb;
            }
            else if(tempa<tempb)//Alice抢完5,6会来抢3,4的
            {
                Alice+=tempa;
                Bob+=tempa;
                tempb-=tempa;
                if(tempb%2==0)
                {
                    Bob+=tempb/2;
                }
                else
                {
                    if(now==1)
                    {
                        now=2;
                        Bob+=tempb/2;
                    }
                    else
                    {
                        now=1;
                        Bob+=tempb/2+1;
                    }
                }
            }
            else
            {
                Alice+=tempb;
                Bob+=tempb;
                tempa-=tempb;
                if(tempa%2==0)
                {
                    Alice+=tempa/2;
                }
                else
                {
                    if(now==1)
                    {
                        now=2;
                        Alice+=tempa/2+1;
                    }
                    else
                    {
                        now=1;
                        Alice+=tempa/2;
                    }
                }
            }
    
            int temp=a[11]+a[12]+a[13]+a[14];//两人一起抢了
            if(temp%2==0)//刚好平分
            {
                Alice+=0;
                Bob+=0;
            }
            else
            {
                if(now==1)
                {
                    now=2;
                }
                else
                {
                    now=1;
                }
            }
            tempa=a[7]+a[8];
            tempb=a[9]+a[10];
            if(tempa==tempb)
            {
                Alice+=0;
                Bob+=0;
            }
            else if(tempa<tempb)//Alice抢完5,6会来抢3,4的
            {
                Alice+=0;
                Bob+=0;
                tempb-=tempa;
                if(tempb%2==0)
                {
                    Bob+=tempb/2;//会留下一个
                }
                else
                {
                    if(now==1)
                    {
                        now=2;
                        Bob+=tempb/2+1;
                    }
                    else
                    {
                        now=1;
                        Bob+=tempb/2;
                    }
                }
            }
            else
            {
                tempa-=tempb;
                if(tempa%2==0)
                {
                    Alice+=tempa/2;
                }
                else
                {
                    if(now==1)
                    {
                        now=2;
                        Alice+=tempa/2;
                    }
                    else
                    {
                        now=1;
                        Alice+=tempa/2+1;
                    }
                }
            }
            Alice+=2*a[1];
            Bob+=2*a[2];
            if(now==1)
            {
                if(Bob>=Alice)printf("Bob\n");
                else printf("Alice\n");
            }
            else
            {
                if(Alice>=Bob)printf("Alice\n");
                else printf("Bob\n");
            }
        }
        return 0;
    }
  • 相关阅读:
    shell基础--变量的数值计算
    shell基础--字符串和变量的操作
    shell基础--shell特殊变量
    Asp.net MVC 控制器扩展方法实现jsonp
    ASP.NET web api 跨域请求
    asp.net Web API简单的特性路由配置
    ASP.Net Web API 输出缓存 转载 -- Output caching in ASP.NET Web API
    基础拾遗 C# Json 与对象相互转换
    内存溢出和内存泄漏
    软件测试面试题(一)
  • 原文地址:https://www.cnblogs.com/kuangbin/p/2652902.html
Copyright © 2020-2023  润新知