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;
}
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;
}
相关文章推荐
- ACM: 图论题 poj 3308 最大流问题
- Android的自定义控件起步
- ACM: 图论题 poj 3177 同 3352
- dos批处理中%~dp0%的说明
- ACM: 图论题 poj 2186 强连通分量
- ACM: 博弈题 poj 1143 状态压缩
- 本周学习的代码(数构 深度 广度 优先遍历)
- [原创]关于设置linux中vim 显示行号
- ACM: 动态规划题 poj&nb…
- ACM: 图论题 poj 3…
- 兴趣学习: opencv 实现画图程序
- 兴趣学习: opencv -- 视频读写, 鼠…
- ACM: 动态规划题 poj 2923
- ACM: 动态规划题 poj&nb…
- ACM: 动态规划题 poj 3093 0-1背包
- ACM: 动态规划题 poj&nb…
- ipvsadm-2 DR模式及自动检测后端服务器状态
- ACM: 动态规划题 poj 3211 背包变…
- ACM: 动态规划题 poj&nb…
- ACM: 动态规划题 poj 3659