• poj 1020 Anniversary Cake (DFS)


    出处: http://blog.csdn.net/lyy289065406/article/details/6683250


    大致题意:

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

     

    解题思路:

    有技巧的DFS

     

    可以把大蛋糕想象为一个蛋糕盒子,然后往里面装小蛋糕。

    装蛋糕时遵循以下原则:

    自下而上,自左至右;

    即先装好盒子底部,再继续往上层装,且装每一层时都靠左边放蛋糕;

    大蛋糕优先装,因为小蛋糕灵活度比较高。

     

    只要把问题变换为上述问题,我想对深搜比较熟悉的同学也会马上得到思路了,这个只是很简单的DFS思路。

     

    但是本题的难点不在于怎样去DFS,而是每放入一个蛋糕后,怎样去标记盒子已经放有蛋糕的位置?

    应该“按列标记”。不但把盒子看做多个1*1个格子,也把小蛋糕看做多个1*1的单位,建立一个一维数组col[ BoxSize ],每放入一个蛋糕,则去记录每列的格子被填充的数目。

    例如在第2~4列放入了一个size=3的小蛋糕,那么col[2]+=3, col[3]+=3, col[4]+=3。有同学会问,为什么行不用计数?要是放入蛋糕后,该蛋糕底部出现部分悬空怎么处理?这个情况是不会出现的,因为当前DFS遵循先把底部放满原则,要是出现悬空,则会回溯。


    #include <iostream>
    #include <cstring>
    
    using namespace std;
    
    int BoxSize; //盒子尺寸
    int n;//蛋糕的总个数
    int SizeNum[11];//各种尺寸的蛋糕个数
    int col[41];//col[i]记录第i列被填充了的格子数
    
    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;
    
            ////检查尺寸为size的蛋糕放入盒子时在纵向和横向是否越界
            if(BoxSize-col[prow]>=size && BoxSize-prow+1>=size)
            {
                //检查盒子从第prow列到第prow+size-1列,共size列的宽度wide中
                //是否每列剩余的空间都足够放入高度为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;
                    //放入尺寸为size的蛋糕
                    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 t;
        cin>>t;
        while(t--)
        {
            memset(SizeNum, 0, sizeof(SizeNum));
            memset(col, 0, sizeof(col));
    
            cin>>BoxSize>>n;
    
            int cnt=0;//记录size>(BoxSize/2)的蛋糕个数
            int area=0;//计算所有蛋糕的面积之和
    
            for(int i=0; i<n; i++)
            {
                int size;
                cin>>size;
    
                area+=size*size;
                SizeNum[size]++;
    
                if(size>BoxSize/2)
                    cnt++;
            }
    
            if(cnt>1|| area!=BoxSize*BoxSize)
            {
                cout<<"HUTUTU!"<<endl;
                continue;
            }
    
            if(DFS(0))
                cout<<"KHOOOOB!"<<endl;
            else
                cout<<"HUTUTU!"<<endl;
    
        }
    
        return 0;
    }
    



    版权声明:本文为博主原创文章,未经博主允许不得转载。

  • 相关阅读:
    js---05 自定义属性
    js---04 属性 this
    js---03属性操作
    js02---字符串
    js01----json,数组
    android framework 02
    android framework 01
    Android Service完全解析,关于服务你所需知道的一切(下)
    Android Framework 记录之二
    Android Framework 记录之一
  • 原文地址:https://www.cnblogs.com/wanglaoda/p/4937133.html
Copyright © 2020-2023  润新知