论分支结构我服谁

这是2017广东工业大学程序设计竞赛决赛中的一个题目

Description

众所周知的是,TMK特别容易迟到,终于在TMK某次又迟到了之后,Maple怒了,Maple大喊一声:“我要跟你决一死战!”然后Maple就跟TMK玩起了一个关于占点的游戏。

Maple在一个无限展开的只有整数点的二维平面上找到两个点,由TMKMaple分别操控这两个点,两人轮流操作,每一次操作中TMKMaple可以把他的点移动一格到上、下、左、右四个方向,当TMK操作时,移动到的这个点会被染成红色,而当Maple操作时,移动到的这个点会被染成蓝色,需要注意的是,两个起始时的两个点也都会被染上相应的颜色,而当任一人走到已经染了不同颜色的点,这个颜色会被覆盖掉,当两个点覆盖在一起时,这个点会被后来的点染色。当游戏结束时染着自己颜色的点就代表被自己占领了。

TMK一下就明白了,这个游戏的目标是让自己占领的点比对方占领的点多,而且要让差值最大。

为了公平一些,Maple决定让TMK来选择先手或后手和让TMK来选择点,相应的Maple就会选择另一个点。

现在给出游戏的总轮数NMaple选择的两个点的坐标(x1y1),(x2y2),要TMK来选择先后手和起始点,假设Maple一定按最优策略来走,问TMK能不能选择先后手和起始点使得自己占领的点比Maple占领的多,如果能,那么同时要求出占领的点数的最大差值。

Input

第一行一个T,代表接下来有T组数据(1<=T<=2000)

每组数据有五个整数N,x1,y1,x2,y2,代表了操作的总轮数N以及选择的两个起始点(x1,y1),(x2,y2),其中1<=N<=10^8-10^8<=x1,y1,x2,y2<=10^8,数据保证两个点不相同。

Output

对于每一组数据,如果TMK占领的点不能比Maple占领的多,那么输出-1,否则输出两个占领点数的最大差值。

Sample Input

4
1 0 0 1 0
2 0 0 1 0
1 0 0 2 0
2 0 0 2 0

Sample Output

2
-1
1
-1
对题闲聊:说实话这题是我做过的分支结构中的最复杂的一题(我不会告诉你们我写了一个小时的!),由于题目中的Maple都是按最优路线走的,这个解释很让人深思,所以这题的主要思路就是什么才是最优思路呢?这很重要,否则,就别想写出来这道题了,还有一个大坑,题目里所说的一轮,不是一轮两个人各走一次,而是一轮一个人走一次,说实话要是一轮两个各走一次的话,TMK就别想赢了O(∩_∩)O~(而且这样这个轮数也没什么大的意义,只能判断在有效轮数之内两个点能否接壤,,还有如果轮数为单数,TMK必须选先手,这样他就能多走一步,这样才有翻盘的机会,还有一个Maple选择问题,他必须选择是否迎战。最优走法嘛。所以需要分析棋盘的压制状况。这很重要,这直接决定了TMK是否要和Maple刚正面,如果被压制了还刚正面我就不吐槽了。
接下来给出几组案例。
 我们假设1是TMK染过色的块,2是Maple染过色的块;
先看步数为奇数的时候,如果多走一步都刚不过那偶数就更没辙了。
由于Maple要走最优路线,那就必须追TMK的尾,即图中1的位置。
如果2追到了1的尾而1无法在2的相邻色块上,那必输,所以TMK
必须向Maple方向走。现在,TMK先走,如何压制?往下走,追
2的尾并且让2无法主动攻击,因为一走右边或上边就会被1染色
2只能往左或者下边走,然后这个时候1来追尾了,这个时候又出现一个问题
该往左还是往下呢?我们说了我们TMK也不是吃素的,如果Maple往左走(比如图二,2往左走了一步)
Maple肯定选择往下走一步,因为这个游戏有一个大前提:!!!!!(重点!!!!)自己
在能压制对方的情况下 染过色的块要尽量
远离敌人,以防被染色。
这样2就手足无措了,又染不到对面的,自己的又要被染色,心痛,这个时候2又要选择了,到底是往右边回去呢,还是往别的地方走呢?
他的选择必须是往回走,因为往别的地方还无法直接接触到1,就算少染一个颜色也没事,因为自己的色块一旦被占领,2的利益损失量就是2,
因为对面多了一个自己少了一个嘛,然往回走的话只会少染一个格子,损失一个颜色,所以这里就要考虑1能否追上2了,由于我们是在能走无限步数的情况下,
所以一定追的了尾,所以2必须往回走,这样的话被占了之后还能立刻占回来。

这里注意下,后文说明的追尾就是能走到对方的初始位置。!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

还有一种情况就是(有限步数的时候)1只能追到2的一个尾巴轮次就结束了,走完了,那2应该选择往别的地方跑,这样多占一个格子,因为被占了之后没有下一步了,所以2就算回去也占不过来,那还不如趁现在多占一个格子。但是这两种情况结果都是一样的,都是被1比2多两个格子,我们可以把这两种情况总结起来,原因如图三图四图五图六

情况一↓
00000
00100
00000
02000
00000
                             ↓图二
00000
00100
00100
22100
00000

图三(有限步数,1只能追到2的尾轮次就结束了,2选择走别的方向,这是结果2两个,1四个,差两个)

00000
00100
20100
21100
00000
图四(无限步数,1追到2的尾的时候轮次还没结束,还能继续走,注意Maple和TMK在同一个位置,但是TMK之后来的所以方块的颜色是1,接下来2就可以占回来)
00000
00100
00100
212100
00000
图五(2占回来)

00000
00100
00100
11200
00000

所以对长远的情况下来说肯定是往回走比较靠谱吧。。

这样的话存在距离差等于3的情况。其实还有更好的办法,后面会有讲解。

如果你们觉得当初图二的时候2应该选择往上走再往右走你们可以自己试试。

好了,最复杂的情况讲述半完毕hhhhhh。//

如果步数是偶数,Maple就不会被TMK牵制,因为就算TMK先占了,由于Maple步数和TMK相同所以他可以占回来。

同样用图一来演示1刚开始肯定往下走这个时候注意了,2并不需要退让,因为自己的步数可以TMK相同,所以就算先被

占了也可以占回来,所以TMK格子永远不会比Maple多。


图七

00000
00100
02100
02000
00000

现在TMK走一步之后Maple再走一步,试问怎样能让TMK占得比Maple多?

这个时候你们如果眼尖的话是不是发现了什么,这种情况就算步数是奇数的时候

最多也只亏损两个格子,所以前面图三四五的时候最少差两个格子,所以不应该逃,而是直接和1刚,这里又要考虑1的步数了,

(现在讨论的又回到奇数步数的时候了)

如果1本来追不上你,这样两者之间只差一个格子,2硬要和1刚,导致1追的上2了,那不是要差两个格子了?所以这个时候要考虑1到底能不能追上2,

追不上咱就跑,追的上咱就刚,反正最多差两个格子到顶了。

所以在1追的上2的情况下(或者说就算Maple从刚开始就跑TMK也追的上的话),这种就是最坏情况了,最多差两个格子。

追不上的话Maple就跑,就差一个格子。

(现在回到偶数步数)

就算1往左走了占了2的格子,由于两个人可以走的步数相同,所以轮次一定还没有结束,2可以往右走,两者可以持平,所以TMK永远无法比Maple格子多。

再考虑下距离差是偶数的时候,

(偶数距离,例如下图,距离为4)

比如

00000
00010
00000
02000
00000
如果TMK往下走或者往左走,Maple只要走其相反的方向就不会被压制,这个情况你们可以试一下。所以刚正面TMK是毫无胜算的,只能跑,这个时候又要考虑距离之间的问题了。如果Maple追的到TMK的尾,那TMK必败无疑,追不到的话如果步数是奇数,那么TMK可以多走,所以,占的格子会比Maple多一格。偶数的话就格子数相平。

所以总结一下以上的情况,

如果是偶数步数,必败无疑(就是TMK占的格子绝对不会比Maple多)。不管追不追的到尾,距离是奇数还是偶数。

否则///奇数步数       TMK肯定先手

{

        先判断距离奇偶性,这个比较重要,

          {

               判断距离1能否追尾2

                不能的话,只能多占一个格子,

                否则占能多占两个格子

          }

          否则,即距离为偶数

         MTK无论如何无法压制Maple,前面有说明

        接下来判断距离

            {

                     追尾的上的话,TMK完蛋了

                       追尾不上,哈哈哈哈,由于TMK先走的,所以多占一个。

            }

}

如果有人能耐着性子看到现在也不容易了,下面

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
int main()
{
    int T;
    scanf("%d",&T); 			//数据的组数 
    while(T--)
    {
        long long n;
        long long x1,y1,x2,y2;
        scanf("%lld%lld%lld%lld%lld",&n,&x1,&y1,&x2,&y2);	//输入数据,这个就不解释了 
        if(n%2==0)								// 判断轮数是否为偶数,偶数的话TMK就别想赢了,单数的话,TMK选先手可以多走一步。
            printf("-1\n");
        else
        {
                if(abs(x1-x2)+abs(y1-y2)%2==0)			 //判断两点之间的x方向上的距离和y方向上的距离之和,是否为偶数,
				//因为棋盘存在压制状况,如果是偶数,那么TMK刚正面就会亏 
                    if(abs(x1-x2)+abs(y1-y2)*2>n)		//判断Maple追不追的到TMK,追不到咱就跑,正面刚不过,因为是先手所以会多一格哈哈哈 
                        printf("1\n");
                    else								//追的到,认输吧 
                        printf("-1\n");
                else									//TMK可以压制Maple 
                    if((abs(x1-x2)+abs(y1-y2)-1)*2>n)	//Maple刚不过只能跑,检查两点间的距离,看看跑的掉不 
                        printf("1\n");			//如果追不到,反正TMK先走的,多一步 
                    else
                        printf("2\n");  		//追得到,TMK人生迎来了光明 
        }
    }
    return 0;
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值