藍橋杯 2015國賽 四階幻方

2021-10-10 10:34:54 字數 1819 閱讀 9033

題目鏈結

把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...