Square
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
题目大意:
给了很多段长度的小木棒,问能不能拼成一个正方形。
解题思路:
1.首先将长度累加,看是不是4的倍数,不是的话就直接不可能了。是的话就求出边长。
2.开始暴力搜索,对每段长度进行DFS,直到出现有一个边凑不成指定边长,说明不可能。
3.可以进行多种剪枝方法比如: 排序,从大到小搜索。 跳过重复的不匹配边。 此处给出一个链接,这道题方法类似但是剪枝要求很高,看了很多题解觉的这篇的源码和思路都写的比较易懂: POJ 1011 Sticks【DFS+剪枝】
源代码:
#include<iostream>
#include<stdio.h>
#include<cstring>
#include<string.h>
#include<vector>
using namespace std;
bool use[24];
int length[24];
int num, avg;
bool dfs(int i, int now, int count) {
if (now == avg) {
i = 0;
now = 0;
if (++count == 4)
return true;
}
for (int j = i; j < num; j++) {
if (!use[j]) {
use[j] = true;
if (now + length[j] <= avg && dfs(j+1, now + length[j], count))
return true;
use[j] = false;
}
}
return false;
}
int main() {
int times, n, start,total;
scanf("%d", ×);
for (int ti = 1; ti <= times; ti++) {
memset(use, false, sizeof(use));
scanf("%d", &num);
total = 0;
for (int i = 0; i < num; i++) {
scanf("%d", &length[i]);
total += length[i];
}
bool result = false;
if (total % 4 == 0) {
avg = total / 4;
result = dfs(0, 0, 0);
}
if (result)
printf("yes\n");
else
printf("no\n");
}
return 0;
}