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