poj 1020 Anniversary Cake——dfs搜索

Anniversary Cake

Description

Nahid Khaleh decides to invite the kids of the “Shahr-e Ghashang” to her wedding anniversary. She wants to prepare a square-shaped chocolate cake with known size. She asks each invited person to determine the size of the piece of cake that he/she wants (which should also be square-shaped). She knows that Mr. Kavoosi would not bear any wasting of the cake. She wants to know whether she can make a square cake with that size that serves everybody exactly with the requested size, and without any waste.

Input

The first line of the input file contains a single integer t (1 ≤ t ≤ 10), the number of test cases, followed by input data for each test case. Each test case consist of a single line containing an integer s, the side of the cake, followed by an integer n (1 ≤ n ≤ 16), the number of cake pieces, followed by n integers (in the range 1…10) specifying the side of each piece.

Output

There should be one output line per test case containing one of the words KHOOOOB! or HUTUTU! depending on whether the cake can be cut into pieces of specified size without any waste or not.

Sample Input

2
4 8 1 1 1 1 1 3 1 1
5 6 3 3 2 1 1 1

Sample Output

KHOOOOB!
HUTUTU!

题意: 有t组测试数据。首先给定大蛋糕的尺寸(方形尺寸)side,现在有n个人会来吃蛋糕,问:这n个人所吃的蛋糕的尺寸能否刚好拼成尺寸是side的大蛋糕的尺寸(n个小正方形能否拼成side*side的大正方形)。

题解: 详情看代码
转载于:https://blog.csdn.net/ZCMU_2024/article/details/89388577

c++ AC 代码

/*思路: DFS
1.我选择按列来放,保证每次填充时选则填充的列剩余未填充的行数>=指定蛋糕的边长
2.假设我们的列的编号是从1开始的,那么我们就要保证当前选定列+选择填充的蛋糕边长-1<=蛋糕的边长
3.有两种情况是直接可以判断结果为"HUTUTU!"的
  1)所有小蛋糕面积的总和!=大蛋糕的面积
  2)存在一个以上小蛋糕的边长>大蛋糕边长/2
*/
#include
#include
#include
using namespace std;
const int Max=1e3+5;
int pos[100],cake[20],side,n; //pos记录第i列的开销,cake记录各种边长蛋糕的个数
/*首先明确填充的顺序:
  1.从左往右填充
  2.从下到上填充
  3.选择蛋糕先大后小
*/
bool DFS(int number)
{
    if(number==n)
        return true;
    int Min=Max;
    int index;
    for(int i=1;i<=side;i+=1)
    {
        if(Min>pos[i])
        {
            Min=pos[i];
            index=i;
        }
    }
    for(int i=10;i>=1;i--)
    {
        /* if((如果不存在边长为i的蛋糕)||(选定列已填充的宽度+将要填充的宽度>给定蛋糕的尺寸)||
           (从当前列开始向右填充的长度>给定蛋糕的尺寸)) 跳过;
        */
        if(!cake[i]||Min+i>side||index+i-1>side)
            continue;
        bool sign=true;
        for(int x=index;x<=index+i-1;x+=1)
        {
            /*从选定列遍历到终止的列,若其中发现某列的开销大于选定列的开销则放弃此次填充
              (原因:因为实际上填充的是一个完整正方形)
            */
            if(pos[x]>Min)
            {
                sign=false;
                break;
            }
        }
        if(!sign)
            continue;
        cake[i]--;
        for(int x=index;x<=index+i-1;x+=1)
            pos[x]+=i;
        if(DFS(number+1))
            return true;
        cake[i]+=1;
        for(int x=index;x<=index+i-1;x+=1)
            pos[x]-=i;
    }
    return false;
}
int main()
{
    std::ios::sync_with_stdio(false);
    int T;
    cin>>T;
    while(T--)
    {
        int pie[20];
        cin>>side>>n;
        int total=0;
        int Count=0;
        memset(cake,0,sizeof(cake));
        memset(pos,0,sizeof(pos));
        for(int i=0;i<n;i+=1)
        {
            cin>>pie[i];
            cake[pie[i]]+=1;
            total+=pie[i]*pie[i];
            if(pie[i]>side/2)
                Count+=1;
        }
        if(total!=side*side||Count>1)
            cout<<"HUTUTU!"<<endl;
        else
        {
            if(DFS(0))
                cout<<"KHOOOOB!"<<endl;
            else
                cout<<"HUTUTU!"<<endl;
        }
    }
    return 0;
}

你可能感兴趣的:(深度优先DFS)