等边三角形
题目描述
小明手上有一些小木棍,它们长短不一,小明想用这些木棍拼出一个等边三角形,并且每根木棍都要用到。例如,小明手上有长度为 1,2,3,3 的 4 根木棍,他可以让长度为 1,2 的木棍组成一条边,另外 2 根分别组成另 2 条边,拼成一个边长为 3 的等边三角形。小明希望你提前告诉他能不能拼出来,免得白费功夫。
输入描述
首先输入一个整数 n n n,表示木棍数量,接下来输入 n n n 根木棍的长度 p i p_i pi。
输出描述
如果小明能拼出等边三角形,输出"yes",否则输出"no"。
用例输入 1
5
1 2 3 4 5
用例输出 1
yes
数据规模与约定
3
≤
n
≤
20
3≤n≤20
3≤n≤20,
1
≤
p
i
≤
10000
1≤p_i≤10000
1≤pi≤10000。
代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int n, flag = 0, sum = 0, tag;
int length[20]; // 木棍长度
int group[3] = {0}; // 三条边的当前边长
void dfs(int i, int index)
{
group[index] += length[i];
if (group[1] > tag || group[0] > tag || group[2] > tag) // 剪枝:一旦有一条边长度大于预期边长tag,该方案不满足
{
group[index] -= length[i]; // 回溯
return;
}
if (group[0] == tag && group[1] == tag) // 一旦有两条边可以达到预期边长tag,则可以构成等边三角形
{
flag = 1;
return;
}
if (i + 1 < n) // 判断:如果没有遍历完所有木棍,则继续递归,否则终止递归
{
// 递归下一根木棍放到三条边中的三种情况
if (!flag)
dfs(i + 1, 0);
if (!flag)
dfs(i + 1, 1);
if (!flag)
dfs(i + 1, 2);
}
group[index] -= length[i]; // 回溯
return;
}
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
cin >> n; // 木棍数量
for (int i = 0; i < n; i++)
{
cin >> length[i];
sum += length[i]; // 统计总长度
}
tag = sum / 3; // 等边三角形边长
if (sum % 3 == 0) // 总长度能被3整除是能构成等边三角形的前提
dfs(0, 0);
if (flag)
cout << "yes";
else
cout << "no";
return 0;
}