POJ 2362 Square
Time Limit: 3000MS | Memory Limit: 65536K | |
---|---|---|
Total Submissions: 27083 | Accepted: 9158 |
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
题目大意
题目意思比较容易理解:给定一定数量不同长度的木棒,判断他们是否能够组成一个正方形
解题思路
给定一定数量的木棒如果将他们组成正方形的话 ,所有木棒长度之和,即周长可以均分为 4 条等长的边,也就是变相的问能否组成长度相同的4条木棒。
本题使用DFS + 剪枝的思想,找到正方形的边长(side = sum / 4)并排序木棒长度,对数组中木棒的长度进行搜索,从起始找到木棒的组合长度为side并已经将组成为side的标记,之后进行深度搜索 深度加一,依次深度搜索 当深度为4的时候意味着找到组成正方形的四条木棒。
使用剪枝法可排除掉没有意义的搜索,提高程序的效率,使用剪枝法要对其有大致的理解:剪枝就是通过某种判断,避免一些不必要的遍历过程,将没有的部分减去,形象地称为剪枝,使用剪枝的核心问题就是剪枝的判断,确定那个枝条应当舍弃,那个枝条应当保留(参考于这里),大致理解了剪枝我们看看这道题那些地方可以剪
- 题目中要求为正方形,边长 % 4 == 0
- 最长的棒子长度必须小于 正方形的边长
#include <cstring>
#include <algorithm>
#include <iostream>
using namespace std;
// stick 表示木棍长度 ,visit 标记数组,side边长
bool visit[20];
int n, side, stick[20];
bool cmp(int a ,int b){
return a > b;
}
/*
num为深度表示已经构成的边数
len 当前一条边拼成的长度
s 下次查找的起始位置
*/
bool dfs(int num, int len, int s){
if(num == 4) return true;
for(int i = s; i < n; i++){
if(visit[i]) continue;
visit[i] = true;
//构成的边 < side
if(len + stick[i] < side){
//搜索构成side的边
if(dfs(num, len + stick[i], i)) return true;
// 找到构成side的边
}else if(len + stick[i] == side){
//在刚刚找到的基础上,搜索标记num+1 len = 0 s =0
if(dfs(num + 1, 0, 0)) return true;
}
// 没找到构成 side 的边就标记为false
visit[i] = false;
}
return false;
}
int main(){
int m;
cin >> m;
for(int i = 0; i < m; i++){
cin >> n;
int sum = 0;
for(int j = 0; j < n; j++){
cin >> stick[j];
sum += stick[j];
}
side = sum / 4;
sort(stick, stick + n, cmp);
if(sum % 4 || side < stick[0]){
cout << "no" << endl;
continue;
}
memset(visit, false,sizeof(visit));
if(dfs(1, 0, 0)) cout << "yes" << endl;
else cout << "no" << endl;
}
}
本篇参考于: