zoj3823--构造

时间:2021-11-03 18:04:01

题目大意:

在n*n(n<=512)的网格上,从边界某个点出发,经过每个点一次且回到边界上,构造出一种方案使拐弯的数量至少为n*(n-1)-1次。

构造方法:
我们可以手算出n=2~6时的方案。

n=2:zoj3823--构造

n=3:zoj3823--构造

n=4:zoj3823--构造

n=5:zoj3823--构造

n=6:zoj3823--构造

观察n=2与n=4、n=3与n=5的情况我们可以得到一种构造方案:

在构造n*n的方案时,先构造(n-2)*(n-2)的方案,再将其对一条斜向右下的直线作对称,然后在剩下的位置不停拐弯。

例如:
构造n=5时,先求出n=3的方案,再将其翻转,得到:
zoj3823--构造

再在它剩下的7个格子里不停拐弯就可以了。注意n为奇数和偶数时转角处的不同。拐弯方式可参照手算出来的方案。

时间复杂度O(T*n^2*log2n)

具体看代码。

代码:

 #include<iostream>
 #include<cstdio>
 #include<cstring>
 using namespace std;
 ][],c[][];
 inline void D2(){
     a[][]=;a[][]=;a[][]=;a[][]=;
 }
 inline void D3(){
     a[][]=;a[][]=;a[][]=;
     a[][]=;a[][]=;a[][]=;
     a[][]=;a[][]=;a[][]=;
 }
 inline void F(int x){
     ;i<=x;i++)
     ;j<=x;j++)c[j][i]=a[i][j];
     ;i<=x;i++)
     ;j<=x;j++)a[i][j]=c[i][j];
 }
 inline void Solve(int x){
     ){D2();return;}
     ){D3();return;}
     Solve(x-);F(x-);cnt=(x-)*(x-);
     ;i<=x-;i++)
     )a[x-][i]=++cnt,a[x][i]=++cnt;][i]=++cnt;
     )a[x][x-]=++cnt,a[x][x]=++cnt,a[x-][x]=++cnt,a[x-][x-]=++cnt;][x-]=++cnt,a[x][x-]=++cnt,a[x][x]=++cnt,a[x-][x]=++cnt;
     ;i>=;i--)
     )a[i][x-]=++cnt,a[i][x]=++cnt;]=++cnt;
 }
 ];
 int Len;
 inline void Print(int x){
     ;x;x/=)S[++Len]=x%;
     );
 }
 int main()
 {
     scanf("%d",&T);
     while(T--){
         scanf("%d",&n);
         )D2();)D3();else Solve(n);
         ;i<=n;i++){
             ;j<n;j++)Print(a[i][j]),putchar(' ');
             Print(a[i][n]);putchar('\n');
         }
     }
     ;
 }

zoj3823