hdu 4277 USACO ORZ (dfs暴搜+hash)
题目大意:有N个木棒,相互组合拼接,能组成多少种不同的三角形。
思路:假设c>=b>=a 然后枚举C,在C的dfs里嵌套枚举B的DFS。
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <vector> #define mod 2000007 using namespace std; int n; int X[20]; bool vis[20]; int ans; long long sum; long long hash[mod]; bool ok(int b,int c) { int a=sum-b-c; if(a+b>c && c>=b && b>=a)return true; return false; } bool work(long long t) { int v=t%mod; while(hash[v]!=t && hash[v]!=-1)//.....之前这里写成了IF 卡了半天再找到。以后要细心。。。 v=(v+10)%mod; if(hash[v]==-1) { hash[v]=t; return true; } return false; } void dfsb(int pos,int c,int b) { //printf("c = %d b = %d\n",c,b); for(int i=pos;i<=n;i++) { if(vis[i])continue; vis[i]=true; b+=X[i]; if(ok(b,c)) { //printf("c = %d,b = %d,a = %d\n",c,b,sum-b-c); int a=sum-b-c; long long t=(long long)a+(long long)b*sum+(long long)c*sum*sum; if(work(t))ans++; } if(b<=c)dfsb(i,c,b); b-=X[i]; vis[i]=false; } } void dfsc(int pos,int c) { for(int i=pos;i<=n;i++) { if(vis[i])continue; vis[i]=true; c+=X[i]; if(c>=sum/3 && c<=sum/2)dfsb(1,c,0);//剪枝 dfsc(i,c); c-=X[i]; vis[i]=false; } } int main() { int T; scanf("%d",&T); while(T--) { scanf("%d",&n); memset(vis,0,sizeof(vis)); memset(hash,-1,sizeof(hash)); sum=0; for(int i=1;i<=n;i++) { scanf("%d",&X[i]); sum+=X[i]; } ans=0; dfsc(1,0); printf("%d\n",ans); } return 0; }