17 背包的bitset优化,当我们要的组合值太大,但是我们要组合的个数较小的话我们可以背包个数不背包容量

  HDU - 5890 

Mr. Fib is a mathematics teacher of a primary school. In the next lesson, he is planning to teach children how to add numbers up. Before the class, he will prepare NN cards with numbers. The number on the ii-th card is aiai. In class, each turn he will remove no more than 33 cards and let students choose any ten cards, the sum of the numbers on which is 8787. After each turn the removed cards will be put back to their position. Now, he wants to know if there is at least one solution of each turn. Can you help him?

Input

The first line of input contains an integer t (t≤5)t (t≤5), the number of test cases. tttest cases follow. 
For each test case, the first line consists an integer N(N≤50)N(N≤50). 
The second line contains NN non-negative integers a1,a2,...,aNa1,a2,...,aN. The ii-th number represents the number on the ii-th card. The third line consists an integer Q(Q≤100000)Q(Q≤100000). Each line of the next QQ lines contains three integers i,j,ki,j,k, representing Mr.Fib will remove the ii-th, jj-th, and kk-th cards in this turn. A question may degenerate while i=ji=j, i=ki=k or j=kj=k.

Output

For each turn of each case, output 'Yes' if there exists at least one solution, otherwise output 'No'.

Sample Input

1
12
1 2 3 4 5 6 7 8 9 42 21 22
10
1 2 3
3 4 5
2 3 2
10 10 10
10 11 11
10 1 1
1 2 10
1 11 12
1 10 10
11 11 12

Sample Output

No
No
No
Yes
No
Yes
No
No
Yes
Yes

例如 :

我们要选择三个物品组合成大小为10000000000,的数值有没有方案,我们用最原始的背包的话有点难实现,但是我们发现

我们要选择的物品数量是挺少的所以我们可以拿物品的个数来作为背包的新容量,这个样子的话又会出现新的问题就是如何知道

我们是否是的到了这个数值,所以我们要标记一下在组合的过程中是否是出现了这个数字,这个时候我们就要用到bitset数组了

一个bitset   1 变量就是一个一维的数组 bitset <length> dp, 就是长度为length的dp数组,2  bitset <length> dp[22] 我们定义了一个 一维的数组,就是一个二维的数组;

1  dp 0 1 2 3 4 5 6 7 8 . . . . . . . . . . . . .. . length-1

2  dp[1] 0 1 2 3 4 5 6 7 .. . . . . . . .. .. .  . .length-1

    dp[2] 0 1 2 3 4 5 6 7... ...  . . .......   ... ..length-1

    dp[3] 0 1 2 3 4 5 6 7.......... . . .  .. . . . . .length-1

    .....

    .....

   dp[22] ... ...............................................length-1

   并且是每一个位置上的数字要么是0要么是1

   前面也遇到过背包,它的实质就是一个组合问题不论是我们要组合出一个新的数值还是,我们要根据现有的条件来求出一个

    最优值我们都是可以用背包的组合性能跟特点来求得,

   假设我们要去两件物品,可以组合出那些数值来 有三件物品 a[1]=2, a[2]=3, a[3]=3;

             3                      2                 1                0

a[1]   000000000   00000000   00000100    00000001

a[2]   000000000   00100000   00001100    00000001

a[3]   100000000   {01100000}   00001100    00000001 

花括号标出的部分是我们要的值那么我们可以看到,下标为6或是为5的位置是1,也就是说明在我们从这三件物品中拿两件的话

会有两个值我们可以获得就是5和6的数值我们可以组合出来;

#include <bits/stdc++.h>
using namespace std;
const int nmax = 55;
typedef long long ll;
#define rep(i,s,n) for(int i=s;i<=n;i++)
#define per(i,n,s) for(int i=n;i>=s;i--)
bitset <90> dp[11];
int a[nmax],n,q;
bool visited[nmax][nmax][nmax];
bool judge(int x, int y, int z){
    rep(i,0,10)  dp[i].reset();
    dp[0][0]=1;
    rep(i,1,n){
       if(i==x||i==y||i==z) continue;
       per(j,9,0)  dp[j+1]|=(dp[j]<<a[i]);
    }

    if(dp[10][87])  return 1;

    return 0;
}
int main(){
  int t;
  scanf("%d",&t);
  while(t--){
    scanf("%d",&n);
    rep(i,1,n)  scanf("%d",&a[i]);
    memset(visited,0,sizeof(visited));
    rep(i,1,n){
       rep(j,i,n){
          rep(k,j,n){
            if(judge(i,j,k)){
                visited[i][j][k]=visited[i][k][j]=true;
                visited[j][i][k]=visited[j][k][i]=true;
                visited[k][i][j]=visited[k][j][i]=true;
            }
          }
       }
    }
    scanf("%d",&q);
    while(q--){
        int i,j,k;
        scanf("%d %d %d",&i,&j,&k);
        if(visited[i][j][k]) printf("Yes\n");
        else   printf("No\n");
    }
  }
  return 0;
}
 

猜你喜欢

转载自blog.csdn.net/qq_39792342/article/details/81903835