藍橋杯2015——完美正方形(DFS 暴力搜尋)
如果一些邊長互不相同的正方形,可以恰好拼出一個更大的正方形,則稱其為完美正方形。
歷史上,人們花了很久才找到了若干完美正方形。比如:如下邊長的22個正方形 2 3 4 6 7 8 12 13 14 15 16 17 18 21 22 23 24 26 27 28 50 60 如【圖1.png】那樣組合,就是一種解法。此時, 緊貼上邊沿的是:60 50 緊貼下邊沿的是:26 28 17 21 18
22階完美正方形一共有8種。下面的組合是另一種: 2 5 9 11 16 17 19 21 22 24 26 30 31 33 35 36 41 46 47 50 52 61 如果告訴你該方案緊貼著上邊沿的是從左到右依次為:47 46 61, 你能計算出緊貼著下邊沿的是哪幾個正方形嗎?
請提交緊貼著下邊沿的正方形的邊長,從左到右,用空格分開。
不要填寫任何多餘的內容或說明文字。
參考:https://blog.csdn.net/qq_34446253/article/details/51470218
#include<cstdio> #include<iostream>
using namespace std;
int arr[]={2,5,9,11,16,17,19,21,22,24,26,30,31,33,35,36,41,50,52,46,47,61}; int flagArr[19]={0}; int draw[155][155]={0};
bool judgment(int x,int y,int n){ //引數定義 n 表示正方形邊長 //1.如果超過畫布邊框 返回false //2.如果畫的正方形與其他正方形重合 返回false //else 返回true if(!(x+n<=155&&y+n<=155)) return false; for(int i=x;i<x+n;i++) for(int j=y;j<y+n;j++) if(draw[i][j]) return false; return true; } void drawing(int x,int y,int n,int m){ //引數定義 n 表示正方形邊長 m 表示正方形編號 //從(x,y)處開始 畫長度為 n 的正方形 其編號為 m for(int i=x;i<x+n;i++) for(int j=y;j<y+n;j++) draw[i][j]=m; } void getCoordinate(int &x,int &y){ //1.我們第一行已經知曉所以可以從46行開始搜尋 //找到我們搜尋的第一行值為0的說明此處未被畫 然後返回 for(int i=47;i<155;i++) for(int j=1;j<155;j++) if(!draw[i][j]){ x=i; y=j; return; } } bool solved(){ //如果全部都已賦值,則返回true for(int i=47;i<155;i++) for(int j=1;j<155;j++) if(!draw[i][j]) return false; return true; } bool dfs(int x,int y){ //深度搜索 //遞迴出口 solved為真,退出迴圈 //else 開始遍歷 /* */ if(solved()) return true; else{ getCoordinate(x,y); for(int k=0;k<19;k++){ if(judgment(x,y,arr[k])){ if(!flagArr[k]){ drawing(x,y,arr[k],arr[k]); flagArr[k]=1; if(dfs(x,y+arr[k])) return true; flagArr[k]=0; drawing(x,y,arr[k],0); } } else break; //退出迴圈原因: /* 1.為什麼不先檢查 flagArr[k]?---只能選擇continue,不節約記憶體 2.小的正方形都裝不下了,大的一定裝不下,所以沒必要迴圈下去 */ } } return false; } int main(){ drawing(1,1,47,47); drawing(1,48,46,46); drawing(1,94,61,61); dfs(47,1); for(int i=1;i<=154;i++){ cout<<draw[154][i]<<' '; i+=draw[154][i]; } return 0; }