#include <iostream>
#include <cstring>
#include <cstdio>
#include <vector>
#include <bitset>
#include <algorithm>
using namespace std;
const int M=55;
int a[M],n;
bool check[M][M][M];//打表
//超时 int dp[M][11][100];//dp[i][j][k]前i个数的取j个之和和能否达到k j<=10
bitset<100> b[12];//b[i][k] 是否存在i个数之和为k
//b[i] |= b[i-1]<<a[j] 表示b[i]这个集合里面的所有的出现的数向右移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
bool Check(int x,int y,int z)
{
for(int i=0;i<=10;i++)
b[i].reset();
b[0][0]=1;
for(int i=1;i<=n;i++)//前i个数
{
if(i==x||i==y||i==z||a[i]>87)
continue;
for(int j=10;j>=1;j--)//取j个
{
b[j]|=(b[j-1]<<a[i]);
//逆推时b[j]为前i个不取a[i]
//b[j-1]<<a[i]为取a[j]
}
}
if(b[10][87])
return true;
else
return false;
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
memset(check,0,sizeof(check));
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
}
//前i个数选10个不选x,y,z时的和能否达到87
//由于q为10W较大 打表出不选的情况check(x,y,z)
for(int x=1;x<=n;x++)//n最坏为50
{
for(int y=x;y<=n;y++)
{
for(int z=y;z<=n;z++)
{
if(Check(x,y,z))
{
check[x][y][z]=1;
}
else
check[x][y][z]=0;
}
}
}
int q;
scanf("%d",&q);
while(q--)
{
int c[3];
scanf("%d%d%d",&c[0],&c[1],&c[2]);
sort(c,c+3);
if(check[c[0]][c[1]][c[2]])
printf("Yes\n");
else
printf("No\n");
}
}
return 0;
}
hdu 5890 01背包(bitset优化)
最新推荐文章于 2023-12-23 20:02:34 发布