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;
}


 

 

你可能感兴趣的:(USACO)