POJ - 1020 Anniversary Cake

题意:有一块边长为BoxSize的正方形的大蛋糕,现在给出n块不同尺寸的正方形的小蛋糕的边长,问是否能把大蛋糕按恰好切割为这n块小蛋糕,要求每块小蛋糕必须为整块。

思路:有技巧性的DFS,这里有一篇写的很好的:点击打开链接

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;

int BoxSize,n;
int SizeNum[11];
int col[41];

bool dfs(int FillNum){
    if (FillNum == n)
        return true;
    int min = 50;
    int prow;
    for (int i = 1; i <= BoxSize; i++)
        if (min > col[i]){
            min = col[i];
            prow = i;
        }
    for (int size = 10; size >= 1; size--){
        if (!SizeNum[size])
            continue;
        int wide = 0;
        if (BoxSize-col[prow] >= size && BoxSize-prow+1 >= size){
            int wide = 0;
            for (int r = prow; r <= prow+size-1; r++){
                if (col[r] <= col[prow]){
                    wide++;
                        continue;
                    }
                    break;
                }
            if (wide >= size){
                int r;
                SizeNum[size]--;
                for (r = prow; r <= prow+size-1; r++)
                    col[r] += size;
                if (dfs(FillNum+1))
                    return true;
                SizeNum[size]++;
                for (r = prow; r <= prow+size-1; r++)
                    col[r] -= size;
            }
        }
    }
    return false;
}

int main(){
    int cas;
    scanf("%d",&cas);
    for (int t = 1; t <= cas; t++){
        memset(SizeNum,0,sizeof(SizeNum));
        memset(col,0,sizeof(col));
        scanf("%d%d",&BoxSize,&n);
        int cnt=0,area=0;
        for (int i = 1; i <= n; i++){
            int size;
            scanf("%d",&size);
            area += size*size;
            SizeNum[size]++;
            if (size > BoxSize/2)
                cnt++;
        }
        if (cnt > 1 || area != BoxSize*BoxSize){
            printf("HUTUTU!\n");
            continue;
        }
        if (dfs(0))
            printf("KHOOOOB!\n");
        else printf("HUTUTU!\n");
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值