B — 问题

Sample Input 1 

2
3 5 6 1
1 2 3
4 40 50 10
10 20 30 25

Sample Output 1

2
2

题意:找符合题意的问题集的数量;

例如:5 <= 1+2+3 <=6 ;   5 <= 2+3 <=6 ;     故问题集的数量为2;

两种方法,而且n的最大值是10,dfs和状态压缩都可以;

(1)下面手动模拟一下dfs的过程:

其中dfs(sum,s,p,cnt), sum代表此时问题集的难度,s代表问题集中难度最大的题,p是难度最小的,cnt是此时问题集的数量;

从dfs(a[0],0,0,1) 开始调用,i=0,sum=a[0]=1,cnt=1,

i =1         dfs(a[0]+a[1],1,0,1)                   sum=3          cnt+1=2                  
i =2         dfs(a[0]+a[1]+a[2],2,0,1)           sum=6          cnt+1=3                 ans++; (1)
i =2         dfs(a[0]+a[2],2,0,1)                   sum=4          cnt+1=2                
i =2         dfs(a[1]+a[2],2,1,1)                   sum=5          cnt+1=2                 ans++; (2)

#include<bits/stdc++.h>
using namespace std;
const int M=15;
int a[M];
int n,l,r,x;	
int ans=0;
void dfs(int sum,int s,int p,int cnt){
	if(sum>=l&&sum<=r&&a[s]-a[p]>=x&&cnt>=2){
		ans++;
	}
	for(int i=s+1;i<n;i++){
		if(sum+a[i]<=r){
			dfs(sum+a[i],i,p,cnt+1);
		}
	}
}
int main()
{
	int t;
	cin>>t;
	while(t--){
		ans=0;
		memset(a,0,sizeof(a));
		scanf("%d %d %d %d",&n,&l,&r,&x);
		for(int i=0;i<n;i++){
			scanf("%d",&a[i]); 
		}
		sort(a,a+n);
		for(int i=0;i<n;i++){
			dfs(a[i],i,i,1);
		}
		printf("%d\n",ans);
	}
	return 0;
}

(2)状态压缩

每个数字的二进制中1表示取,0表示不取。

if( i & (1<<j) )//这里是最为关键的一步,这里相当于时取出这个数字的这一位是1还是0,假设有一个数字10100,&操作是都为1时,结果才为1,1<<j ,在第j位永远都是1

这个方法是问的学长,自己不是很懂。。。。(哎)

#include <bits/stdc++.h>
using namespace std;
const int MAXN=20;
const int INF=0x3f3f3f3f; 
int a[MAXN];

int main()
{
	int T;
	scanf("%d",&T);
	while(T--){
		memset(a,0,sizeof(a));
		int n,l,r,x;
		scanf("%d%d%d%d",&n,&l,&r,&x);
	    for (int i = 0; i <n ; ++i)
	        scanf("%d",&a[i]);
	    int cnt=(1<<n)-1,ans=0;
	    for(int i=1;i<=cnt;i++){
	    	int Min=INF,Max=-INF,num,sum=0;
	    	for(int j=0;j<n;j++){
	    		if(i&(1<<j)){//这里是最为关键的一步,
				//这里相当于时取出这个数字的这一位是1还是0,
				//假设有一个数字10100,&操作是都为1时,结果才为1,1<<j ,
				//在第j位永远都是1
	    			sum+=a[j];
	    			Min=min(Min,a[j]);
	    			Max=max(Max,a[j]);
	    			num++;
				}
			}
			if(sum>=l&&sum<=r&&Max-Min>=x&&num>=0)
				ans++;
		}   
	    printf("%d\n",ans);
	}
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_41555192/article/details/82291618