描述
给定 n 根木棍,第 i 根长度为 ai
现在你想用他们拼成尽量多的面积大于 0 的三角形,要求每根木棍只能被用一次,且不能折断
请你求出最多能拼出几个
输入
第一行一个正整数 n
第二行 n 个正整数 a1 … an
1 ≤ n ≤ 15
1 ≤ ai ≤ 109
输出
输出最多能拼出几个三角形
样例输入
6
2 2 3 4 5 6
样例输出
2
思路:
一开始看n这么小,以为是暴力,结果不行,看了一眼题解,才知道是状压dp,之前一只没明白过,现在终于懂了。
大致是用二进制表示某个位置取或不取,这样一串01串可以表示n个位置每个点的状态了。对于这个题目,我们需要枚举能组成三角形的情况,然后记录构成三角形的时候选了哪三条边。然后状压dp
#include <cstdio>
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn = (1<<15)+5;
int dp[maxn];
int state[maxn];
bool judge(long long a, long long b, long long c)
{
if ( a+b > c && c - a < b) return true;
return false;
}
int main()
{
long long A[20];
int n;
cin >> n;
for (int i = 0; i < n; ++i)
cin>>A[i];
sort(A,A+n);
int res = 0;
int cnt = 0;
for (int i = 0; i < n; ++i) {
for (int j = i+1; j < n; ++j) {
for (int k = j+1; k < n; ++k) {
if (judge(A[i],A[j],A[k])) {
state[++cnt] = (1<<i)|(1<<j)|(1<<k);
}
}
}
}
dp[0] = 1;
for (int i = 1; i <= cnt; ++i) {
for (int j = (1<<n) - 1; j >= 0; --j) {
if(dp[j] && !(j&state[i])) {
dp[j|state[i]] = dp[j] + 1;
res = max(res,dp[j]);
}
}
}
cout << res << endl;
return 0;
}