hdu 4277 USACO ORZ 搜索+set判重

http://acm.hdu.edu.cn/showproblem.php?pid=4277

题意:

给出n条线段,每条线段的长度为li (1 <= li <= 10000) 1 <= N <= 15。才开始想到了爆搜算了一下时间复杂度O(3^15)*15勉强可以,可是在判重问题上一直很纠结,不知道该怎么处理,素以就放下了。赛后看了看解题报告,可谓经典啊。。爆搜所有的组合,然后set(或者hash判重),这里由于li<=10000 N <=15 所以最大的长度肯定小于10000000000000000ll,在__int64的表示范围之内,所以我们只需要将a,b, c转化成一个数inert进去即可。 例如a = 1500 b = 2536 c = 12156 我们通过ll tmp = 1000000000000ll*a + 1000000ll*b + c;计算得到1500000253600012156然后插入到set里面。 这里我们严格规定a > b > c 来规定三角形,避免了1 2 3 ,3 2 1这样的重复。

 

View Code
#include <iostream>

#include <cstdio>

#include <cstring>

#include <algorithm>

#include <cmath>

#include <queue>

#include <stack>

#include <set>

#include <map>

#include <string>



#define CL(a,num) memset((a),(num),sizeof(a))

#define iabs(x)  ((x) > 0 ? (x) : -(x))

#define Min(a,b) (a) > (b)? (b):(a)

#define Max(a,b) (a) > (b)? (a):(b)



#define ll __int64

#define inf 0x7f7f7f7f

#define lc l,m,rt<<1

#define rc m + 1,r,rt<<1|1

#define pi acos(-1.0)

#define test puts("<------------------->")

#define maxn 100007

#define M 100007

#define N 17

using namespace std;

//freopen("din.txt","r",stdin);



set<ll>Set;

int arr[N];

int n;







void dfs(int num,int a,int b,int c){

    if (num == n){

        if (a > b || b > c || a > c) return ;

        if (a && b && c && a + b > c){

            ll tmp = 1000000000000ll*a + 1000000ll*b + c;

            Set.insert(tmp);

        }

        return ;

    }

     dfs(num + 1,a + arr[num],b,c);

     dfs(num + 1,a,b + arr[num],c);

     dfs(num + 1,a,b,c + arr[num]);

}



int main(){

    int t,i;

    scanf("%d",&t);

    while (t--){

        scanf("%d",&n);

        for (i = 0; i < n; ++i){

            scanf("%d",&arr[i]);

        }

        Set.clear();

        dfs(0,0,0,0);

        printf("%d\n",Set.size());

    }

    return 0;

}

 

 

 

你可能感兴趣的:(USACO)