如果一些边长互不相同的正方形,可以恰好拼出一个更大的正方形,则称其为完美正方形。
历史上,人们花了很久才找到了若干完美正方形。比如:如下边长的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.youkuaiyun.com/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;
}