完美正方形 蓝桥真题

题目略

搜索剪枝 每次从左上角开始一行行找 找第一个空白位置 看能不能放下某个正方形 当产生完全覆盖之后即找到答案 类似方法的题还有zoj 3209

两点注意

1 先对19个正方形升序排序 只要某个没用过得正方形放不下了 后边的肯定放不下直接跳过(如果是矩形就没法这样贪心) 

2 如果初始标定的三个正方形放在了左上角 找第一个空白位置就从左上开始 如果放在了右下角 那就从右下开始 不然在很长一段时间内搜索是基本没啥剪枝的 因为周围太空旷了 应该是直到与标定的三个正方形相遇之后剪枝才开始强力的

 

 

#include <bits/stdc++.h>
using namespace std;
const int maxn=200;

int book[maxn][maxn];
int ary[maxn],flag[maxn];
int num,gou;

void paint(int x,int y,int len,int val)
{
    int i,j;
    for(i=x;i<=x+len-1;i++){
        for(j=y;j<=y+len-1;j++){
            book[i][j]=val;
        }
    }
}

bool judge(int x,int y,int len)
{
    int i,j;
    if(x+len-1>154||y+len-1>154) return 0;
    for(i=x;i<=x+len-1;i++){
        for(j=y;j<=y+len-1;j++){
            if(book[i][j]!=-1) return 0;
        }
    }
    return 1;
}

bool dfs(int area)
{
    int i,j,px,py;
    /*
    if(gou<10){
        printf("*%d*\n",area);
        gou++;
    }
    */
    if(area==23716) return 1;
    for(i=1;i<=154;i++){
        for(j=1;j<=154;j++){
            if(book[i][j]==-1){
                px=i,py=j;
                break;
            }
        }
        if(j!=155) break;
    }
    for(i=0;i<num;i++){
        if(judge(px,py,ary[i])){
            if(!flag[i]){
                paint(px,py,ary[i],i);
                flag[i]=1;
                if(dfs(area+ary[i]*ary[i])) return 1;
                paint(px,py,ary[i],-1);
                flag[i]=0;
            }
        }
        else break;
    }
    return 0;
}

int main()
{
    int i,pre;
    num=19;
    2 5 9 11 16 17 19 21 22 24 26 30 31 33 35 36 41 50 52
    for(i=0;i<num;i++){
        scanf("%d",&ary[i]);
    }
    memset(book,-1,sizeof(book));
    //47 46 61
    paint(1,1,47,19);
    paint(1,47+1,46,20);
    paint(1,47+46+1,61,21);
    if(dfs(8046)){
        pre=-1;
        for(i=1;i<=154;i++){
            if(book[154][i]!=pre){
                pre=book[154][i];
                printf("%d ",ary[book[154][i]]);
            }
        }
        printf("\n");
    }
    else printf("gg\n");
    return 0;
}


 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值