构造/sgu109 Magic of David Copperfield II

题意

  给出一个n*n的棋盘,现有游戏规则如下:

  玩家一开始在左上角的格子里,魔术师给出多条指令,每条指令包含两个信息:

  1、玩家走的步数(>=n,且不重复)

  2、魔术师要删除的格子

  魔术师可以删除一些这一步走不到的格子,并继续发出指令,知道所有格子(除了一个)被删除,并且玩家被逼到了这个格子中。

  求发出指令的一组可行方案

 

分析

  不难发现,第一条指令肯定是让玩家走n步,之后步数逐渐增加

  我们可以将这个棋盘像国际象棋棋盘那样,黑白染色

  易证,走奇数步时会走到另一种颜色上,所以我们只需要每次让玩家走到另一种颜色上去,把相反颜色的格子删掉

  但是这样删有两点问题:1、如果一开始n就为偶数,那么怎么走

               2、删相反色的格子时,会形成“断路”,把玩家困在某些地方,而其他的格子未被删除

  首先,第一点很好处理,如果为偶数,则先把周围一圈走不到的格子删掉,然后+1,把偶数转换为奇数,继续做

  至于第二点,则是这道题的核心:如何删除格子?

  我们知道,全删了肯定不行,那么,只需要像剥皮一样,一圈一圈地删除,那么就能把玩家困在中间某个格子里了

  具体实现:

    首先,先走n步,把大于与左上角曼哈顿距离的格子删掉,因为这些格子是达不到的

        曼哈顿距离:横坐标之差+纵坐标之差

    然后就要处理奇偶性了:如果为偶数,则+1,转换为奇数;否则+2

    设一个dist为每次的曼哈顿距离与当前点的差。一层一层向里删除格子,知道这个差dist<=2,游戏结束,玩家已经被困在中间格子内。

 

Accepted Code

 1 /*
 2     PROBLEM:sgu109
 3     AUTHER:Rinyo
 4     MEMO:曼哈顿距离 构造
 5 */
 6 
 7 #include<cstdio>
 8 int n;
 9 int main()
10 {
11     scanf("%d",&n);
12     printf("%d",n);
13     
14     for (int i=1;i<=n;i++)
15         for (int j=1;j<=n;j++)
16             if (i-1+j-1>n) printf(" %d",(i-1)*n+j);
17     printf("\n");
18 
19     int dist=n+2;
20     int now=n;
21     while (dist>2) 
22     {
23         now++;
24         while (now%2==0) now++;
25         printf("%d",now);
26         for (int i=1;i<=n;i++)
27             for (int j=1;j<=n;j++)
28                 if (i+j==dist) printf(" %d",(i-1)*n+j);
29         printf("\n");
30         dist--;
31     }
32 }

 

posted @ 2012-12-07 22:41  Rinyo  阅读(470)  评论(0编辑  收藏  举报