题目链接 http://acm.hdu.edu.cn/showproblem.php?pid=1518
Problem Description Given a set of sticks of various lengths, is it possible to join them end-to-end to form a square?
Input The first line of input contains N, the number of test cases. Each test case begins with an integer 4 <= M <= 20, the number of sticks. M integers follow; each gives the length of a stick - an integer between 1 and 10,000.
Output For each case, output a line containing "yes" if is is possible to form a square; otherwise output "no".
Sample Input 3 4 1 1 1 1 5 10 20 30 40 50 8 1 7 2 6 4 4 3 5
Sample Output yes no yes |
题目大意: 给定m根火柴(木棍),判断能否拼成一个正方形。
题解(参考了下网上的代码):
用深搜,dfs函数里面标记好已经拼了几条边,拼满4条边就OK,然后需要标记当前正在拼凑的边已有的长度,每次搜索遍历可选的每根火柴,有两种选择,让遍历的这根火柴拼入当前边或者不拼。拼的话判断拼后此边的长度,如果大于了正方形边长,就continue尝试下一条边,等于边长就拼下一条边。小于边长的话,可以选择将火柴加入该边,继续dfs找,或者不加直接continue...
#include <cstdio>
#include <algorithm>
# include <cstring>
using namespace std;
int len[25]; // 火柴长度
bool used[25] ; // 火柴使用标记
int m; // 火柴数目
int edge; // 边长
bool dfs(int depth, int length,int pos) {
if(depth == 4)
return true; // 能拼成正方形
// 遍历火柴
for(int i = pos;i < m;i++) {
if(used[i] == true)
continue;
used[i] = true;
if(len[i] + length == edge){
if(dfs(depth+1,0,0))
return true;
}
else if(len[i] + length > edge) {
used[i] = false;
continue;
}
else if(len[i] + length < edge)
if(dfs(depth,length+len[i],i+1))
return true;
used[i] = false;
}
return false;
}
int main() {
int t;
int count = 0; // 火柴总长度
scanf("%d",&t);
while(t--) {
// 初始化
memset(used,0,sizeof(used));
count = 0;
scanf("%d",&m);
for(int i = 0;i < m;i++) {
scanf("%d",&len[i]);
count += len[i];
}
if(count%4 != 0 || m < 4) {
printf("no\n");
continue;
}
count /= 4; // 正方形边长
edge = count;
if(dfs(0,0,0))
printf("yes\n");
else
printf("no\n");
}
return 0;
}