• hdu5890(背包,bitset)


    题意:给你n(n<=50)个数,m( m<=1e5 )次询问,每次询问给你三个数,问在给出的数里面存不存在任意取10个(不包含这三个数)的数的和刚好为87,每次询问输出Yes/No。

     1)bitset?

      C++中可以直接用的一个类。

      bitset<num> name;

      可以看作一个大小为num的数组,里面的元素只能是0或1,有趣的是它能进行和数组一样的操作又能把它当做一个整体(当做一个二进制数)来进行位运算操作。

      1个应用:当做一个数的集合,可以用一个name<<a对集合中的所有元素+a操作(若集合为空,则操作无效),用|符实现两个集合的取交集。

      例如:name1 : 0000010010001001(包含0,3,7,10四个元素)

         name1<<2 :0001001000100100(包含2,5,9,12四个元素)

         name1|name1<<2 :0001011010101101(包含0,3,7,10,2,5,9,12 八个元素,相当于只用了两个位操作就得到了对该集合所有元素加上2/不加上2 的所有结果)

     2)本题分析

      dp分析即可,Bitset[10](使用10个数)由Bitset[9]获得。初始化所有元素为空,但要设置一个含0元素的集合,具体见代码。

      分析下时间复杂度:50*50*50*50*10=6.25e7 (超时的边缘)

      //如果用01背包来做这题,dp[10][87][0/1],时间复杂度:6.25e7*87=5.4375e9

    上代码,交了好几次,基本都卡过去了,但最好也只是902ms(在G++上交)

     

    #include<stdio.h>
    #include<stdlib.h>
    #include<iostream>
    #include<math.h>
    #include<queue>
    #include<string.h>
    #include<algorithm>
    #include<bitset> 
    #define PI acos(-1.0)
    using namespace std; 
    int n,a[60];
    bool reco[60][60][60][2]; //记录该3个数是否计算过,是否yes 
    
    bool check(int x,int y,int z)
    {
    	if(reco[x][y][z][0]==1) return reco[x][y][z][1];
    	
    	bitset<90> bs[12];
    	
    	bs[0][0]=1;
    	for(int i=1;i<=n;i++)
    	{	if(*(a+i)>87) continue;
    		if(i==x||i==y||i==z) continue;
    	
    		for(int j=10;j>=1;j--)
    			*(bs+j)|=*(bs+j-1)<<*(a+i);
    			
    		if(bs[10][87]==1) break;
    	}
    	reco[x][y][z][1]=(bs[10][87]==1);
    	reco[x][y][z][0]=1;
    	return reco[x][y][z][1];
    }
    int main()
    {
    	int T;
    	scanf("%d",&T);
    	while(T--)
    	{	
    		memset(reco,0,sizeof(reco));
    		scanf("%d",&n);
    		for(int i=1;i<=n;i++)
    			scanf("%d",&a[i]);
    			
    		int q;
    		scanf("%d",&q);
    		while(q--)
    		{
    			int x[5];
    			scanf("%d%d%d",x,x+1,x+2);
    			sort(x,x+3);
    			if(reco[x[0]][x[1]][x[2]][1]) printf("Yes
    ");
    			else if(check(x[0],x[1],x[2])) printf("Yes
    ");
    			else printf("No
    ");
    		}
    	}
    }
    

     

    以及AtCoder Grand Contest #020 by tourist  C题 (单纯bitset)

    链接:https://agc020.contest.atcoder.jp/tasks/agc020_c 

    AC代码:

    #include<stdio.h>
    #include<stdlib.h>
    #include<iostream>
    #include<math.h>
    #include<queue>
    #include<string.h>
    #include<bitset> 
    #define PI acos(-1.0)
    using namespace std; 
    
    int main()
    {
    	bitset<4000005> bs(1);
    	int n,x,sum=0;
    	scanf("%d",&n);
    	
    	for(int i=0;i<n;i++)
    		{
    			scanf("%d",&x);
    			bs|=bs<<x;
    			sum+=x;
    		}
    	if(n==1)
    	{
    		printf("%d
    ",sum);
    		return 0;
    	}
    	for(int i=(double)sum/2.0+0.5;i<=sum;i++)
    		{
    			if(bs[i]==1)
    			{
    				printf("%d
    ",i);
    				break;
    			}
    		}
    	return 0;
    }
    

      

  • 相关阅读:
    ARC071 简要题解
    ARC070 简要题解
    ARC069 简要题解
    ARC068 简要题解
    ARC067 简要题解
    ARC066 简要题解
    ARC065 简要题解
    长链剖分优化dp三例题
    CF815D Karen and Cards 官方题解翻译
    [九省联考2018] IIIDX 线段树+贪心
  • 原文地址:https://www.cnblogs.com/lnu161403214/p/8322268.html
Copyright © 2020-2023  润新知