蓝桥杯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.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;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值