您的位置:首页 > 其它

hdu 5890 bitset+背包思想

2016-09-22 20:35 417 查看
链接:戳这里

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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: