hdoj 2183 奇数阶魔方(II) 【模拟】+【法】

时间:2021-08-17 13:23:51

比赛的时候花了一个多小时,以做不做

分析:可观察:中间是(n*n+1)/2, 中间的上面是n*n,以下是1, 左边是n,右面是(n*n+1)-n,并且正对角线是最左上对到最右下端添加(+1)。另外一条对角线是最右上到最左下递减(-n) ,其它对角线也是这种规律。

难点:模拟的时候数据有点杂,非常easy搞错,要细心点。

心得:做题的时候要先确定思路是正确的,而且要履好思路之后在写程序。

代码:

#include <cstdio>
#include <cstring>
int s[25][25];
int n;
void leup(int x, int y){ //左上
int i;
i = 1;
while(i < x&&i < y){
s[x-i][y-i] = s[x-i+1][y-i+1]-1; ++i;
}
}
void rido(int x, int y){ //右下
int i = 1;
while(x+i<=n&&y+i<=n){
s[x+i][y+i] = s[x+i-1][y+i-1]+1; ++i;
}
}
void riup(int x, int y){//右上
int i = 1;
while(x-i>0&&y+i<=n){
s[x-i][y+i] = s[x-i+1][y+i-1]-n; ++i;
}
}
void ledo(int x, int y){//左下
int i = 1;
while(x+i<=n&&y-i>0){
s[x+i][y-i] = s[x+i-1][y-i+1]+n; ++i;
}
}
int main(){
int t;
scanf("%d", &t);
while(t --){
scanf("%d", &n);
int mid = n-n/2;
s[mid][mid] = (n*n+1)/2;
s[mid-1][mid] = n*n;
s[mid+1][mid] = 1;
s[mid][mid-1] = n;
s[mid][mid+1] = (n*n+1)-n;
leup(mid, mid);//对角线
ledo(mid, mid);
riup(mid, mid);
rido(mid, mid);
for(int i = 1; i < mid; ++i){ //垂直对角线上的点的线
//leup(mid, mid);
//ledo(mid, mid);
riup(mid-i, mid-i);
ledo(mid-i, mid-i);
ledo(mid+i, mid+i);
riup(mid+i, mid+i);
}
leup(mid, mid-1); //确定最接近对角线而且平行对角线的线
ledo(mid, mid-1);
rido(mid, mid+1);
riup(mid, mid+1); leup(mid-1, mid);
riup(mid-1, mid);
rido(mid+1, mid);
ledo(mid+1, mid); for(int i = 1; i < mid-1; ++i){ //垂直上面确定的线上的点的线
ledo(mid-i, mid-1-i);
riup(mid-1-i, mid-i);
ledo(mid+1+i, mid+i);
riup(mid+i-1, mid+i);
}
for(int i = 1; i <= n; ++ i){
for(int j = 1; j <= n; ++j){
printf("%4d", s[i][j]);
}
printf("\n");
}
}
return 0;
}

版权声明:本文博客原创文章。博客,未经同意,不得转载。