题意:输入一个n,表示在n*n的矩阵中填1~n,使每行每列以及所有正对角线所有反对角线均出现1~n一次。若存在,输出Yes和矩阵,否则输出No;
思路:比赛的时候没思路。将1~n换为0~n较好处理一些。先只考虑0的位置,每行将0向一个方向移动固定格子数,枚举所需的移动步数,
若满足条件(无同行同列同对角线)则Yes,1~n以相同步数移动;否则为No;
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; int n,m,flag; int pos[5050],pre[5050]; int main() { freopen("avangard.in","r",stdin); freopen("avangard.out","w",stdout); int i,j,k,cnt; while(scanf("%d",&n)!=EOF) { cnt=0; for(i=2;i<n-1;i++)//枚举移动格数 { flag=1; for(j=1;j<n;j++)//枚举移动次数 { cnt=i*j%n;//0所在位置 if(cnt==0) flag=0;//同列 else if(cnt==j) flag=0;//正对角线上 else if((cnt+j)==n) flag=0;//反对角线上 } if(flag==1) { cnt=i;break; } } if(n==1) { printf("Yes ");printf("1 ");continue; } for(i=1;i<=n;i++) pos[i]=i; if(!flag) printf("No "); else{ printf("Yes "); for(i=1;i<=n;i++) { for(j=1;j<=n;j++) pre[pos[j]]=j; for(j=1;j<=n;j++) { if(j==1) printf("%d",pre[j]); else printf(" %d",pre[j]); }printf(" "); for(j=1;j<=n;j++) { pos[j]+=cnt;//位置右移,即数左移 if(pos[j]>n) pos[j]-=n; } } } } return 0; }