看到敏感的GEEK字样,果断先读了这题,然后演算纸上各种划拉。。。
题意:构造反幻方(貌似就是和幻方相反的意思)。实际就是个简单的找规律,
我的构造方法:当大于等于5阶时,按左到右,上到下顺序放入1到N*N
对幻方的阶数分奇偶讨论下
奇数:行和,列和,对角和都是相应中间数的N倍,满足a*N(a为正整数)所以只有正中间列和行还有对角的4个相等,只需调换相应的几个数使其不为a*N形式,且互不相等即可,由于阶数大于等于5 ,可以找到相应的调换使相应的和变成a*N+1、a*N+2,a*N-1,a*N-2(3阶会出现a*N1-2与a*N2+1相等的情况)。
偶数:行、列对角和都满足4*n+2、这时只有2个对角和能相等,当阶数大于4时直接把中间的4个数随便调换2个就可以了,构造出2个4*n型的数(4阶情况出现2个4*N型数相等的)。
3和4阶的话直接输出样例即可。
构造方法有很多,有在网上找到什么公式的是蛇形排列好像也满足。还有朴素的构造方法就是随机生成矩阵,然后各种搜索变换,直到满足条件为止。
代码有点绕直接输出就好
#include <cstdio>
#include <string.h>
int ans[205][205];
int I=0;
void swap (int &a,int &b)
{
a^=b^=a^=b;
}
int main ()
{
int n,i,j;
int cas;
scanf("%d",&cas);
while (cas--)
{
scanf("%d",&n);
int t=0;
for (i=0 ; i<n ; ++i)
for (j=0 ; j<n ; ++j)
{
ans[i][j]=++t;
}
if(n==3)
{
ans[0][0]=7;ans[0][1]=5;ans[0][2]=2;
ans[1][0]=1;ans[1][1]=4;ans[1][2]=8;
ans[2][0]=3;ans[2][1]=6;ans[2][2]=9;
}
else if(n==4)
{
ans[0][0]=2;ans[0][1]=8;ans[0][2]=15;ans[0][3]=1;
ans[1][0]=5;ans[1][1]=12;ans[1][2]=10;ans[1][3]=16;
ans[2][0]=6;ans[2][1]=9;ans[2][2]=4;ans[2][3]=14;
ans[3][0]=3;ans[3][1]=7;ans[3][2]=11;ans[3][3]=13;
}
else
if(n&1)
{
swap(ans[n/2][n/2],ans[n/2][n/2+1]);
swap(ans[n/2-1][n/2+1],ans[n/2-1][n/2-1]);
}
else
{
swap(ans[n/2-1][n/2-1],ans[n/2-1][n/2]);
}
printf("Case #%d:\n",++I);
for (i=0 ; i<n ; ++i)
{
int sum=0;
for (j=0 ; j<n ; ++j)
{
printf("%d ",ans[i][j]);
}
printf("\n");
}
}
return 0;
}