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

 

 

 

posted @ 2012-09-12 19:56  E_star  阅读(229)  评论(0编辑  收藏  举报