题目大意:
在n*n(n<=512)的网格上,从边界某个点出发,经过每个点一次且回到边界上,构造出一种方案使拐弯的数量至少为n*(n-1)-1次。
构造方法:
我们可以手算出n=2~6时的方案。
n=2:
n=3:
n=4:
n=5:
n=6:
观察n=2与n=4、n=3与n=5的情况我们可以得到一种构造方案:
在构造n*n的方案时,先构造(n-2)*(n-2)的方案,再将其对一条斜向右下的直线作对称,然后在剩下的位置不停拐弯。
例如:
构造n=5时,先求出n=3的方案,再将其翻转,得到:
再在它剩下的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