hdu 5890 bitset+背包思想



链接:戳这里


Eighty seven

Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 102400/102400 K (Java/Others)

Problem Description
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 N cards with numbers. The number on the i-th card is ai. In class, each turn he will remove no more than 3 cards and let students choose any ten cards, the sum of the numbers on which is 87. 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), the number of test cases. t test cases follow.
For each test case, the first line consists an integer N(N≤50).
The second line contains N non-negative integers a1,a2,...,aN. The i-th number represents the number on the i-th card. The third line consists an integer Q(Q≤100000). Each line of the next Q lines contains three integers i,j,k, representing Mr.Fib will remove the i-th, j-th, and k-th cards in this turn. A question may degenerate while i=j, i=k or j=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


题意:

给出n个数,q个询问i,j,k,每次要求去掉1~3个数,问剩下的数是否存在选出10个数的总和为87


思路:

1:n=50 所以询问最多只有50*50*50,可以预处理出答案然后O(1)输出

2:对于每对i,j,k,去掉这个几个数后,对剩下的数01背包思想处理

问题抽象为:从n-3个物品中取出10个数使得总和为87

dp[i][j]表示取i个数是否能达到总和为j的状态  每个数取或不取(2^10)+一些剪枝(但是这样会T

3:考虑bitset<100> b[11] 

b[i][j]表示当前存在i个数且总和为j的情况用bitset统计好了

b[i] |= b[i-1]<<a[j] 表示b[i-1]这个集合里面的所有的出现的数向右移a[j]个位置(其实就是理解为每个数加a[j]的操作),取抑或是a[j]这个数不取的情况

看一个bitset的用法

当前b[0][2]=1  b[0][5]=1  

b[0]<<2  bitset[0]里面的所有数出现的位置向右移两个位置

      0 1 2 3 4 5 6 7 8 9 10 

       0  0 1 0  0 1 0  0  0 0  0

       0  0 0  0  1 0 0  1 0  0 0


代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<string>
#include<vector>
#include <ctime>
#include<queue>
#include<set>
#include<map>
#include<list>
#include<stack>
#include<iomanip>
#include<cmath>
#include<bitset>
#define mst(ss,b) memset((ss),(b),sizeof(ss))
///#pragma comment(linker, "/STACK:102400000,102400000")
typedef long long ll;
typedef long double ld;
#define INF (1ll<<60)-1
#define Max 1e9
using namespace std;
int f[55][55][55];
int a[55];
int n,q;
bitset <100> b[11];
bool check(int i,int j,int k){
    for(int l=0;l<=10;l++) b[l].reset();
    b[0][0]=1;
    for(int l=1;l<=n;l++){
        if(l!=i && l!=j && l!=k && a[l]<=87){
            for(int o=10;o>=1;o--){
                b[o]|=b[o-1]<<a[l];
            }
        }
    }
    if(b[10][87]) return true;
    return false;
}
int c[5];
int main(){
    /*bitset<10> B[10];
    B[0][5]=1;
    B[0][2]=1;
    B[0]<<2;
    cout<<B[0]<<endl;*/
    int T;
    scanf("%d",&T);
    while(T--){
        scanf("%d",&n);
        for(int i=1;i<=n;i++) scanf("%d",&a[i]);
        mst(f,0);
        for(int i=1;i<=n;i++){
            for(int j=i;j<=n;j++){
                for(int k=j;k<=n;k++){
                    if(check(i,j,k)) f[i][j][k]=1;
                    else f[i][j][k]=0;
                }
            }
        }
        scanf("%d",&q);
        while(q--){
            scanf("%d%d%d",&c[1],&c[2],&c[3]);
            sort(c+1,c+4);
            if(f[c[1]][c[2]][c[3]]) printf("Yes\n");
            else printf("No\n");
        }
    }
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值