给n个木棍 让用所有木棍组成三角形 木棍必须全部用上 可以用多个木棍构一边 问能组成多少不同的三角形 有一边长度不等的两个三角形视为不同方案
枚举木棍 每个木棍可以加在三边 这样不断搜 结果需要不重复 所以每次都让传入的参数从大到小 用一个结构体和set去重 深搜的时候也要剪枝否则超时
剪枝方案就是之前出现的状态再次出现剪掉
也是数据水 自己出组15根棍子的活活卡到3s……
代码如下:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <set>
#define swap(a,b) a += b, b = a-b, a -= b
using namespace std;
typedef struct Stran
{
int a,b,c;
bool operator < (const struct Stran s)const
{
if(a == s.a) return b == s.b? c > s.c: b > s.b;
return a > s.a;
}
}Stran;
set <Stran> s;
int n,sum,num[15];
void soot(int &a, int &b, int &c)
{
if(b > a) swap(a,b);
if(c > a) swap(a,c);
if(c > b) swap(b,c);
}
int dfs(int pos,int a,int b,int c,int rest)
{
if(pos == n)
{
if(b && c && a && b+c>a && !s.count(Stran{a,b,c}))
{
s.insert(Stran{a,b,c});
return 1;
}
return 0;
}
if(rest + b + c <= a || s.count(Stran{a,b,c})) return 0;
s.insert(Stran{a,b,c});
int ans = 0;
int t1,t2,t3;
t1 = a+num[pos];
t2 = b;
t3 = c;
soot(t1,t2,t3);
ans += dfs(pos+1,t1,t2,t3,rest-num[pos]);
t1 = a;
t2 = b+num[pos];
t3 = c;
soot(t1,t2,t3);
ans += dfs(pos+1,t1,t2,t3,rest-num[pos]);
t1 = a;
t2 = b;
t3 = c+num[pos];
soot(t1,t2,t3);
ans += dfs(pos+1,t1,t2,t3,rest-num[pos]);
return ans;
}
/*
1
15
1 2 10 321 546 12 4654 10000 1564 231
6541
5645
51
231
564
3363
卡3s……
*/
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
s.clear();
scanf("%d",&n);
sum = 0;
for(int i = 0; i < n; ++i)
{
scanf("%d",&num[i]);
sum += num[i];
}
printf("%d\n",dfs(0,0,0,0,sum));
}
return 0;
}