您的位置:首页 > 其它

ACM: 搜索题 poj 1020

2016-05-19 23:26 411 查看
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!

 

题意: 给出num个小正方形, 问能否拼成n*n大小的大正方形.

 

解题思路:

     1.
一开始我想到是动态规划-状态压缩, 但是很快打消念头, 因为每个小正方形大小可能不一.

       
无法子问题重叠, 不符合动态规划条件.(我没想出来怎么DP)

    
2. 搜索, 范围最大16个小正方形, 大小1<=size<=10,
16*10*10 = 40*40, 范围搜索还是可以.

       
设: a[i]表示size = i的正方形的个数;

          
 g[i]表示第i行用了前g[i]列(这样可以节省空间 和方便搜索)

    
3. 搜索策略:

       
(1). 大的正方形比较难处理, 小的正方形比较容易, 先从大的开始.

       
(2). 每次都从最左上角开始找出可以放置的位置.

     4.
最后要记住小正方形面积当然要等于大正方形才可以拼成.

 

代码:

#include <cstdio>

#include <iostream>

#include <cstring>

using namespace std;

#define MAX 41

#define MAXSIZE 11

int n, num;

int a[MAXSIZE], g[MAX]; //sqrt(16*10*10) = 40

int sum;

int getMin()

{

 int minR, size = MAX;

 for(int i = 1; i <= n; ++i)

 {

  if( g[i] < size
)

  {

   size =
g[i];

   minR =
i;

  }

 }

 return minR;

}

bool dfs(int cur)

{

 int i, j, minR;

 bool flag;

 if( cur == num ) return true;

 minR = getMin(); //找出最左上角的位置

 for(i = MAXSIZE; i >= 1;
--i)

 {

  flag = false;

  if( a[i] != 0
&& minR+i-1 <= n
&& g[minR]+i <= n )
//范围和个数

  {

   for(j = minR;
j < minR+i; ++j) //判断是否可以放置这个正方形.

    if(
g[j] > g[minR] ) break;

   if( j ==
minR+i ) flag = true; //标记可以放置

  }

  if( flag )

  {

   a[i]--;

   for(j = minR;
j < minR+i; ++j)

    g[j]
+= i; //记录已经放置后状态

   if(
dfs(cur+1) ) return true;

   for(j = minR;
j < minR+i; ++j)

    g[j]
-= i;

   a[i]++;

  }

 }

 return false;

}

int main()

{

// freopen("input.txt", "r", stdin);

 int caseNum;

 scanf("%d", &caseNum);

 while(caseNum--)

 {

  memset(a, 0, sizeof(a));

  memset(g, 0, sizeof(g));

  scanf("%d %d",
&n, &num);

  int temp;

  sum = 0;

  for(int i = 0; i
< num; ++i)

  {

   scanf("%d",
&temp);

   a[temp]++;

   sum +=
temp*temp;

  }

  if( sum != n*n )
//面积不一样当然拼不成

   printf("HUTUTU!\n");

  else

  {

   if( dfs(0) ==
true )

    printf("KHOOOOB!\n");

   else

    printf("HUTUTU!\n");

  }

 }

 return 0;

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: