1020 - Anniversary Cake

这是一道搜索题,搜索的时候有2个剪枝:1、搜索顺序。如果两个正方形的边长相同,则在同一层只搜索一次就可以。2、在每一层搜索时,从每一列中最小的行开始,如果正方形放不下,换个较小的。第一个条件很重要,如果不注意会超时。在存矩形的时候有个优化,只用一个一维数组存,表示这一列已经放了多少行。

这道题自己想了很长时间,还是不会,后来看了别人的思路,觉得自己也曾这样想过,但一直不能不会怎么存就没写下去,现在算是会了,但是不够兴奋,毕竟不是自己做出来的,还要多做题,多涨经验。

看了网上不少的题解,几乎都是这个方法,但交上后最好的也才是32ms,真不知那些0ms是怎么出来的。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
int edg, n;
int used[100], v[20];
int dfs(int cur)
{
    if(cur == n) return 1;
    int row = 100, colum = 0;
    for(int i = 1; i <= edg; i++){
        if(row > used[i]){
            row = used[i];
            colum = i;
        }
    }
    for(int i = 10; i > 0; i--){
        if(v[i] && row + i <= edg && colum + i - 1 <= edg){
            int flag = 0;
            for(int j = colum; j < colum + i; j++){
                if(used[j] > row){
                    flag = 1;
                    break;
                }
            }
            if(!flag){
                v[i]--;
                for(int j = colum; j < colum + i; j++)
                    used[j] += i;
                if(dfs(cur + 1)) return 1;
                v[i]++;
                for(int j = colum; j < colum + i; j++)
                    used[j] -= i;
            }
        }
    }
    return 0;
}
int main()
{
    //freopen("input.txt", "r", stdin);
    int nCase, sum, s;
    scanf("%d", &nCase);
    while(nCase--){
        scanf("%d %d", &edg, &n);
        sum = 0;
        memset(v, 0, sizeof(v));
        for(int i = 0; i < n; i++){
            scanf("%d", &s);
            v[s]++;
            sum += s * s;
        }
        if(sum != edg * edg){
            printf("HUTUTU!\n");
        }else{
            memset(used, 0, sizeof(used));
            if(dfs(0)) printf("KHOOOOB!\n");
            else printf("HUTUTU!\n");
        }
    }
    return 0;
}




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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值