【HDOJ 4277】 USACO ORZ
给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; }