题目大意:
n*n的图片,从左往右,从上到下,依次编号为1-n*n。
观众从图片1出发,按照魔术师所给的指令k1(k1>=n),移动k1步(只能上下左右),之后魔术师删除一些图片(观众当前所在图片之外的),再给指令k2(k2>k1),观众再移动k2步,魔术师再删除一些图片,如此下去,直到图片剩下最后一张。现在要求输出每次魔术师所给的指令k1、k2、……以及删除的图片。
分析:
1、每次删除的必然是给定k后,观众无法到达的图片。
2、删除时应保证图片间的连通性,可从外围删除来保证。
3、若观众移动奇数步,则观众必然可以从当前图片所在的副对角线(i+j=m1)走到另外一条副对角线(i+j=m2)上的某个图片,此时可删除i+j=m1上的所有图片
于是有了下面的删除方案:
1、首先第1步走n步,可以发现右下脚部分(副对角线i+j=n+2以下)是无法到达的,先将该部分删除。
2、考虑n,如果n为偶数,那么下次应该走n+1步;若n为奇数,则走n+2步,这样观众必然不会处于当前副对角线(i+j=n+2)上,此时将该副对角线上图片的删除。
3、此时n已经是奇数,每次+2,依次删除右下到左上的副对角线上的图片即可。
#include<iostream>
#include<cstdio>
using namespace std;
int main()
{
int n,i,j,d,step;
while(~scanf("%d",&n))
{
step=n;
printf("%d",step);
for(i=1;i<=n;++i)
for(j=1;j<=n;++j) if(i+j>n+2) printf(" %d",(i-1)*n+j);
puts("");
for(d=n+2;d>2;--d)
{
if(step&1) step+=2;
else ++step;
printf("%d",step);
for(i=1;i<=n;++i)
for(j=1;j<=n;++j) if(i+j==d) printf(" %d",(i-1)*n+j);
puts("");
}
}
return 0;
}