日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

【蓝桥杯 - 真题】六角幻方(dfs+剪枝)

發布時間:2023/12/10 编程问答 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【蓝桥杯 - 真题】六角幻方(dfs+剪枝) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

標題:六角幻方

? ? 把 1 2 3 ... 19 共19個整數排列成六角形狀,如下:

? ? * * *
? ?* * * *
? * * * * *
? ?* * * *?
? ? * * *

? ? 要求每個直線上的數字之和必須相等。共有15條直線哦!

? ? 再給點線索吧!我們預先填好了2個數字,第一行的頭兩個數字是:15 13,參見圖【p1.png】,黃色一行為所求。

? ? 請你填寫出中間一行的5個數字。數字間用空格分開。

? ? 這是一行用空格分開的整數,請通過瀏覽器提交答案,不要填寫任何多余的內容(比如說明性的文字等)

解題報告:

? 好久沒寫搜索了,,當個練習。

不難發現每一行的值的和應該是38,所以我們已經有了三個已知數字了。

根據對稱性把這三個數放在每一行的開始,相當于有了三個已知行的行首,然后按行dfs,同時判斷是否湊夠了38,如果超了38那就直接return就行,這一點可以用附初始值為比較大的值(這里用了100000)來實現。如果還沒填滿這一行但是和已經大于38了? 或者? 都填滿了并且還不是38,那就return。這應該是最優秀的剪枝了,是每一步都會有剪枝。當然如果不這樣剪枝,而是直接: 每一行都填滿了再判斷是否等于38,也可以。

最終答案:

10 12 16
13 4 2 19
15 8 5 7 3
14 6 1 17
9 11 18

AC代碼:

#include<cstdio> #include<iostream> #include<algorithm> #include<queue> #include<map> #include<vector> #include<set> #include<string> #include<cmath> #include<cstring> #define F first #define S second #define ll long long #define pb push_back #define pm make_pair using namespace std; typedef pair<int,int> PII; const int MAX = 2e5 + 5; int a[55][55],all[55] = {0,10,13,15,0,0}; int up[55] = {0,3,4,5,4,3}; bool vis[55],ok[55][55]; bool cc() {if(a[1][2]+a[2][2]+a[3][2]+a[4][1]!=38) return 0;if(a[1][3]+a[2][3]+a[3][3]+a[4][2]+a[5][1]!=38) return 0;if(a[2][4]+a[3][4]+a[4][3]+a[5][2]!=38) return 0;if(a[3][5]+a[4][4]+a[5][3]!=38) return 0;if(a[1][3]+a[2][4]+a[3][5]!=38) return 0;if(a[1][2]+a[2][3]+a[3][4]+a[4][4]!=38) return 0;if(a[1][1]+a[2][2]+a[3][3]+a[4][3]+a[5][3]!=38) return 0;if(a[2][1]+a[3][2]+a[4][2]+a[5][2]!=38) return 0;if(a[3][1]+a[4][1]+a[5][1]!=38) return 0;return 1; } bool check() {if(a[1][2]+a[2][2]+a[3][2]+a[4][1]!=38 && a[1][2]+a[2][2]+a[3][2]+a[4][1]<100000) return 0;if(a[1][3]+a[2][3]+a[3][3]+a[4][2]+a[5][1]!=38 && a[1][3]+a[2][3]+a[3][3]+a[4][2]+a[5][1]<100000) return 0;if(a[2][4]+a[3][4]+a[4][3]+a[5][2]!=38 && a[2][4]+a[3][4]+a[4][3]+a[5][2]<100000) return 0;if(a[3][5]+a[4][4]+a[5][3]!=38 && a[3][5]+a[4][2]+a[5][3]<100000) return 0;if(a[1][3]+a[2][4]+a[3][5]!=38 && a[1][3]+a[2][4]+a[3][5]<100000) return 0;if(a[1][2]+a[2][3]+a[3][4]+a[4][4]!=38 && a[1][2]+a[2][3]+a[3][4]+a[4][4]<100000) return 0;if(a[1][1]+a[2][2]+a[3][3]+a[4][3]+a[5][3]!=38 && a[1][1]+a[2][2]+a[3][3]+a[4][3]+a[5][3]<100000) return 0;if(a[2][1]+a[3][2]+a[4][2]+a[5][2]!=38 && a[2][1]+a[3][2]+a[4][2]+a[5][2]<100000) return 0;if(a[3][1]+a[4][1]+a[5][1]!=38 && a[3][1]+a[4][1]+a[5][1]<100000) return 0; return 1; } void dfs(int x,int y) {if(x == 6) {if(cc() == 0) return;for(int i = 1; i<=5; i++) {for(int j = 1; j<=up[i]; j++) {printf("%d ",a[i][j]);}printf("\n");}return; }if(check() == 0) return;if(ok[x][y]) {dfs(x,y+1);return;}for(int i = 1; i<=19; i++) {if(vis[i]) continue;if(all[x] + i > 38) continue;if(y == up[x]) {if(all[x] + i != 38) continue;else {all[x] += i;vis[i] = 1;a[x][y] = i;dfs(x+1,1);a[x][y] = 100000;all[x] -= i;vis[i] = 0;return;}}vis[i] = 1;all[x] += i;a[x][y] = i;dfs(x,y+1);a[x][y] = 100000;vis[i] = 0;all[x] -= i;} } int main() {for(int i = 1; i<=5; i++) {for(int j = 1; j<=5; j++) a[i][j] = 100000;}a[1][1]=10;a[2][1]=13;a[3][1]=15;ok[1][1]=1;ok[2][1]=1;ok[3][1]=1;vis[10]=1;vis[13]=1;vis[15]=1;dfs(1,1);return 0 ; } //19:00-19:20/* 10 12 16 13 4 2 19 15 8 5 7 3 14 6 1 17 9 11 18*/

?

總結

以上是生活随笔為你收集整理的【蓝桥杯 - 真题】六角幻方(dfs+剪枝)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。