• hdu 4277 USACO ORZ


    USACO ORZ

    Time Limit: 5000/1500 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
    Total Submission(s): 5470    Accepted Submission(s): 1802


    Problem Description
    Like everyone, cows enjoy variety. Their current fancy is new shapes for pastures. The old rectangular shapes are out of favor; new geometries are the favorite.
    I. M. Hei, the lead cow pasture architect, is in charge of creating a triangular pasture surrounded by nice white fence rails. She is supplied with N fence segments and must arrange them into a triangular pasture. Ms. Hei must use all the rails to create three sides of non-zero length. Calculating the number of different kinds of pastures, she can build that enclosed with all fence segments. 
    Two pastures look different if at least one side of both pastures has different lengths, and each pasture should not be degeneration.
     

    Input
    The first line is an integer T(T<=15) indicating the number of test cases.
    The first line of each test case contains an integer N. (1 <= N <= 15)
    The next line contains N integers li indicating the length of each fence segment. (1 <= li <= 10000)
     

    Output
    For each test case, output one integer indicating the number of different pastures.
     

    Sample Input
    1 3 2 3 4
     

    Sample Output
    1
     

    Source
     

    Recommend
    liuyiding   |   We have carefully selected several similar problems for you:  4276 4274 4268 4272 4267 

    我好菜啊。。。

    一道挺水的题帮别人调了很久。。。

    最后还是求助师兄。。

    主要还是hash部分

    我hash好菜啊。。。

    注意根据三条边算出的hash值相同就认为三条边的方案相同

    所以投进add函数里的hash值不能先取余mod

    我这里用的是unsigned long long 自然溢出

    这是我帮别人调的代码(其实很大部分都是我改过来的。。。)

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    int t,n,a[16],tot=0,l1,l2,summ;
    const int mod=903457;
    int last[mod+10];
    struct node
    {
    	int pre;
    	unsigned long long too;
    	void clear()
    	{
    		pre=0,too=0;
    	}
    }e[2000005];
    void add(unsigned long long val)
    {
    	int x=val%mod;
    	for(int i=last[x];i;i=e[i].pre) if(e[i].too==val) return;
    	e[++tot].too=val,e[tot].pre=last[x],last[x]=tot;
    }	
    bool check(unsigned long long val)
    {
    	int i=last[val%mod];
    	while(i&&e[i].too!=val) i=e[i].pre;
    	return i>0;
    }
    void dfs(int x,int l1,int l2)
    {
    	if(x>n+1)	return;
    	if(l1>0&&l2>0&&l1<=l2&&l2<=summ-l1-l2)
    		if((l1+l2)>(summ-l1-l2)&&(summ-l2)>l2&&(summ-l1)>l1)
    		{	
    		    unsigned long long ans=l1;
    		    ans=ans*1000000007+l2;
    		    ans=ans*1000000007+summ-l1-l2;
    			if(check(ans)==0)		add(ans);
    		}
    	dfs(x+1,l1,l2);
    	dfs(x+1,l1,l2+a[x]);
    	dfs(x+1,l1+a[x],l2);
    	return;
    }
    int main()
    {
    	scanf("%d",&t);
    	for(int i=1;i<=t;i++)
    	{
    		memset(last,0,sizeof(last));
    		for(int j=1;j<=tot;j++)	e[j].clear();
    		tot=0;
    		scanf("%d",&n);
    		summ=0;
    		for(int j=1;j<=n;j++)		
    		{
    			scanf("%d",&a[j]);
    			summ+=a[j];
    		}	
    		if(n<3) printf("0
    ");
    		else 
    		{
    			dfs(1,0,0);
    			printf("%d
    ",tot);
    		}	
    	}
    	return 0;
    }

    下面是我自己写的代码:

    我用的是枚举子集的子集

    注意枚举子集的子集的复杂度是3^n的

    所以要先2^n处理出每个状态的边值

    大大优化了程序的时间效率

    由于dfs常数大

    所以我的程序比上面快了三倍左右

    #include<cstdio>
    #include<cstring>
    const int mod=903457,K=1000000007;
    int tin[(1<<15)+100];
    struct node
    {
    	unsigned long long val;
    	int next;
    	void clear()
    	{
    		val=0;next=0;
    	}
    }e[2000000];
    int a[16];
    int cnt=0;
    int first[mod+5];
    inline void add(unsigned long long val)
    {
    	int x=val%mod;
    	for(int i=first[x];i;i=e[i].next)
    	if(e[i].val==val)return;
    	e[++cnt].val=val,e[cnt].next=first[x],first[x]=cnt;
    }
    inline bool check(unsigned long long val)
    {
    	int i ;
    	for(i=first[val%mod];i;i=e[i].next)	if(e[i].val==val)	break;
    	return i>0;
    }
    int main()
    {
    	int n;int sum=0;
    	int t;
    	scanf("%d",&t);
    	while(t--)
    	{
    		memset(first,0,sizeof(first));
    		for(int i=1;i<=cnt;i++)	e[i].clear();
    		cnt=0;sum=0;
    		scanf("%d",&n);
    		for(int i=1;i<=n;i++)		scanf("%d",&a[i]),sum+=a[i];
    		int top=(1<<n)-1;
    		for(int i=0;i<=top;i++)	
    		{
    			int j=i,cnt=1;int su=0;
    			while(j)
    			{
    				if(j&1)	su+=a[cnt];
    				j=j>>1;
    				cnt++;
    			}
    			tin[i]=su;
    		}
    		for(int sta=1;sta<=top;sta++)
    		{
    			for(int s=sta;s;s=(s-1)&sta)
    			{
    				int l1=tin[s],l2=tin[sta^s],l3=sum-l1-l2;
    				if(l2==0||l3==0||l1==0)	continue;	
    				if((l1+l2)>l3&&(l1+l3)>l2&&l2+l3>l1&&l1<=l2&&l2<=l3)
    				{
    					unsigned long long val=l1;
    					val=val*K+l2;
    					val=val*K+l3;
    					if(check(val)==0)	add(val);
    				}
    			}
    		}
    		printf("%d
    ",cnt);
    	}
    	return 0;
    }

  • 相关阅读:
    悲悯心洞悉真相
    查看逍遥模拟器端口号
    delphi中Tstringlist分割字符串的用法
    delphi中httpencode使用注意事项
    DELPHI常用类型及定义单元
    左旋转字符串
    链表中倒数第k个节点
    二叉树镜像
    用两个栈实现队列
    从尾到头打印链表
  • 原文地址:https://www.cnblogs.com/Brian551/p/7352993.html
Copyright © 2020-2023  润新知