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