【qduoj】奇數階幻方 (構造)
阿新 • • 發佈:2018-12-09
題幹:
C語言_魔方陣
描述
魔方陣是一個古老的智力問題,它要求在一個m×m的矩陣中填入1~m2的數字(m為奇數),使得每一行、每一列、每條對角線的累加和都相等,如下為5階魔方陣示例。
15 8 1 24 17
16 14 7 5 23
22 20 13 6 4
3 21 19 12 10
9 2 25 18 11
輸入
輸入一個數n,表示矩陣的大小,保證n<100且n為奇數
輸出
輸出一個矩陣,每個元素之間以一個空格分隔
答案不唯一,輸出一個題目要求的矩陣即可
輸入樣例 1
5
輸出樣例 1
15 8 1 24 17 16 14 7 5 23 22 20 13 6 4 3 21 19 12 10 9 2 25 18 11
解題報告:
可以找到規律構造,以(1,n/2+1)這個點為1,然後向左上擴充套件,如果最上面了就迴圈到最下面,如果到最左邊了就迴圈到最右邊,如果該點被填過值了,那就到他下面那個點,然後就可以構造出這個圖形了。
剛開始是用搜索寫的:
#include<bits/stdc++.h> using namespace std; int n,flag,sum; bool vis[505]; int maze[505][505]; bool fitr1(int x) { int res = 0; for(int i = 1; i<=n; i++) { res += maze[x][i]; } if(res != sum) return 0; else return 1; } bool fitr2(int x ,int y){ int res = 0; for(int i = 1; i<=y; i++) { res += maze[x][i]; } if(res >= sum) return 0; else return 1; } bool dui(int x,int y) { int res = 0; for(int i = 1; i<=x; i++) { res += maze[i][i]; } if(res >sum ) return 0; res = 0; for(int i = 1; i<=x; i++) { res += maze[i][n-i+1]; } if(res >sum ) return 0; return 1; } bool fitc(int x,int y) { int res = 0; for(int i = 1; i<=x; i++) { res += maze[i][y]; } if(res > sum) return 0; else return 1; } bool ff() { int resr[105] = {0},resc[105] = {0},res = 0; for(int i = 1; i<=n; i++) { for(int j = 1; j<=n; j++) { resr[i] += maze[i][j]; resc[j] += maze[i][j]; } } for(int i = 1; i<=n; i++) { if(resr[i] != sum || resc[i] != sum) return 0; } // for(int i = 1; i<=n; i++) res += maze[i][i]; if(res != sum ) return 0; res = 0; for(int i = 1; i<=n; i++) res += maze[i][n-i+1]; if(res != sum ) return 0; return 1; } void dfs(int x,int y) { // printf("x = %d y = %d\n",x,y); if(x == n+1) { if(ff()) flag = 1; return ; } if(flag == 1) return ; for(int i = 1; i<=n*n; i++) { if(vis[i]) continue; maze[x][y] = i; if(flag == 1) return ; if(x == y) { if(!dui(x,y)) continue; } // if(!fitc(x,y)) continue; if(y == n) { // if(!fitr1(x)) continue; vis[i] = 1; dfs(x+1,1); if(flag == 1) return ; vis[i] = 0; } else { // if(!fitr2(x,y)) continue; vis[i]=1; dfs(x,y+1); if(flag == 1) return ; vis[i] = 0; } } } int main() { cin>>n; for(int i = 1; i<=n*n; i++) { sum += i; } sum/=n; dfs(1,1); for(int i = 1; i<=n; i++) { for(int j = 1; j<=n; j++) { printf("%d%c",maze[i][j],j==n ? '\n' : ' '); } } return 0 ; }
然而發現只能輸入3的時候輸出,輸入5的時候就跑不出來了。最後一項也是,9^15次方,肯定跑不出來呀。
AC程式碼:
#include<cstdio> #include<queue> #include<string> #include<cstring> #include<cmath> #include<map> #include<iostream> #include<algorithm> #define ll long long const ll mod = 1e9+7; using namespace std; int maze[105][105]; int main() { int n; cin>>n; maze[1][(n+1)/2] = 1; int cur=2,tmp = n; int x = 1,y = (n+1)/2; while(cur <= n*n) { if(x == 1) { if(y == 1) { maze[x+1][y] = cur++; x++;tmp = n; continue; } else { for(int i = 1; i<=n; i++) { if(maze[tmp][y-1] != 0) tmp--; else break; } maze[tmp][y-1] = cur++; x=tmp;y--;tmp = n; } } else if(y == 1) { for(int i = 1; i<=n; i++) { if(maze[x-1][tmp] != 0) tmp--; else break; } maze[x-1][tmp] = cur++; x--;y=tmp;tmp=n; } else if(maze[x-1][y-1] != 0 ) { maze[x+1][y] = cur++; x++; } else { maze[x-1][y-1] = cur++; x--,y--; } } for(int i = 1; i<=n; i++) { for(int j = 1; j<=n; j++) { printf("%d%c",maze[i][j],j == n ? '\n' : ' '); } } return 0 ; }