題目鏈結
把1~16的數字填入4x4的方格中,使得行、列以及兩個對角線的和都相等,滿足這樣的特徵時稱為:四階幻方。
四階幻方可能有很多方案。如果固定左上角為1,請計算一共有多少種方案。
比如:
1 2 15 16
12 14 3 5
13 7 10 4
8 11 6 9
以及:
1 12 13 8
2 14 7 11
15 3 10 6
16 5 4 9
就可以算為兩種不同的方案。
請提交左上角固定為1時的所有方案數字
暴力肯定是要暴力的,如果純暴力複雜度就是 16
!16!
16!,顯然不可取,我們通過觀察不難發現,每一行的和是固定的,就是 34
3434
,我是這麼考慮的:
因為數字 1
11 是固定的,所以 1
11 所在的行與列的那三個元素和肯定為 33
3333
,所以我們可以先用 dfs 算出三個數和為 33
3333
的所有情況,一共 19
1919
種,我們可以從中挑兩個放在 1
11 所在的行與列,剩下的 9
99 個數全排列即可,最壞情況的複雜度為 19∗19
∗6∗6
∗9
!19*19*6*6*9!
19∗19∗
6∗6∗
9!,但剪枝後的實際複雜度會大大降低,具體剪枝步驟的注釋見**,我的程式跑了大概三分鐘,裡面寫了乙個計時程式,答案是 416
41641
6,ac**如下:
#include
using
namespace std;
bool vis[20]
;int r[5]
,ans[10]
[10],sum=0;
vector<
int>a,b,v;
vectorint>>s;
void
dfs()if
(flag)
continue
;//如果挑出來的行與列有元素重合直接跳出
for(
int k=
1; k<=
16;k++)if
(!vis[k]
) v.
push_back
(k);
dowhile
(next_permutation
(v.begin()
, v.
end())
);}while
(next_permutation
(b.begin()
,b.end()
));}
while
(next_permutation
(a.begin()
,a.end()
));//暴力遍歷所有情況
a.clear()
,b.clear()
,v.clear()
;}}}
void
dfs(
int x,
int id)
if(x<
0||id>4)
return
;for
(int i=r[id-1]
+1;i<=
16;i++)}
}void
run(
)int
main()
藍橋杯2015決賽 四階幻方
萬萬沒想到能拿到省一,以為第一次能拿個省二就不錯了,有些意外。那麼就從此題再次開啟我的藍橋杯刷題之旅把!求第i行的和 if sum 34 return0 return1 bool check for int j 0 j 4 j 列 return1 void dfs int step return i...
四階幻方 藍橋杯 DFS
答案 416 用next permutation 全部排列的話會超時 所以用dfs搜尋,只搜尋前三行就好,前三行確定之後,第四行也就確定 include include include include using namespace std int vis 17 a 5 5 int ans 0 in...
藍橋杯 四階幻方 C語言
把1 16的數字填入4x4的方格中,使得行 列以及兩個對角線的和都相等,滿足這樣的特徵時稱為 四階幻方。四階幻方可能有很多方案。如果固定左上角為1,請計算一共有多少種方案。比如 1 2 15 16 12 14 3 5 13 7 10 4 8 11 6 9 以及 1 12 13 8 2 14 7 11...