Square
Time Limit: 3000MS | Memory Limit: 65536K | |
Total Submissions: 22779 | Accepted: 7894 |
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
能做,就是。。。。
看大神排序剪枝优化以后才过了,排序以后对于组边的时候过大的边可以舍去不用了,减少了很多不必要的搜索
#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
int M, a[100], tem, sum;
bool vis[100], flag;
void dfs(int n, int pos, int cou) {
if (n != 0) {
//没有组成一边
//注意flag,如果已经组成正方形就没必要继续了
for (int i = pos; !flag && i < M && a[i] <= n; i++) {
if (!vis[i]) {
vis[i] = true;
dfs(n - a[i], i + 1, cou); //继续往大搜索
vis[i] = false;
}
}
} else {
//组成一边
if (cou == 4) {
flag = true;
} else {
dfs(tem, 0, cou + 1);
}
}
}
int main()
{
int N;
scanf("%d", &N);
while(N--) {
memset(vis, false, sizeof(vis));
scanf("%d", &M);
sum = 0;
int maxn = -1;
for (int i = 0; i < M; i++) {
scanf("%d", &a[i]);
sum += a[i];
maxn = max(a[i], maxn);
}
if (sum % 4 != 0) {
puts("no");
continue;
}
tem = sum / 4;
//如果最大的边比正方形的边大
//一定组不成
if (maxn > tem) {
puts("no");
continue;
}
//对边排好序,在DFS的时候
sort(a, a + M);
flag = false;
dfs(tem, 0, 1); //分别找4条边
if (flag) {
puts("yes");
} else {
puts("no");
}
}
return 0;
}
另一种等价写法,但是递归边界有所不同,递归一定要看清楚入口处的状态是什么,是完成了还是待完成的,每个变量对应的状态的准确含义是什么一定要
搞清楚
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
int N, s[30], tem;
bool vis[30];
bool dfs(int pos, int ans, int cou) {
///注意dfs状态,dfs(pos, ans, cou)
///其中cou表示“已完成”cou个,ans是组边时“已完成”的和,pos是“待计算”的位置
if (cou == 4) return true;
if (ans != tem) {
for (int i = pos; i < N && ans + s[i] <= tem; i++) {
if (!vis[i]) {
vis[i] = true;
if (dfs(i + 1, ans + s[i], cou)) {
return true;
}
vis[i] = false;
}
}
}
else {
//if (cou == 4) return true;
if (dfs(0, 0, cou + 1))
return true;
}
return false;
}
int main()
{
int T;
scanf("%d", &T);
while (T--) {
scanf("%d", &N);
int sum = 0;
for (int i = 0; i < N; i++) {
scanf("%d", &s[i]);
sum += s[i];
}
if (sum % 4 != 0) {
puts("no");
continue;
}
tem = sum / 4;
sort(s, s + N);
memset(vis, false, sizeof(vis));
if (dfs(0, 0, 0)) {
puts("yes");
}
else {
puts("no");
}
}
return 0;
}