zoukankan      html  css  js  c++  java
  • 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;
    }

  • 相关阅读:
    【笔记】网易微专业-Web安全工程师-04.WEB安全实战-7.SQL回显注入
    【笔记】网易微专业-Web安全工程师-04.WEB安全实战-6.文件上传
    【笔记】网易微专业-Web安全工程师-04.WEB安全实战-5.文件包含
    【笔记】网易微专业-Web安全工程师-04.WEB安全实战-4.CSRF
    zoom和transform:scale的区别
    图片上黑色透明遮罩的实现
    如何实现两行文本增多显示省略号
    H5如何实现一行三列布局
    H5瀑布流如何实现
    H5一行显示两个正方形
  • 原文地址:https://www.cnblogs.com/Brian551/p/7352993.html
Copyright © 2011-2022 走看看