背包。dp[i]=1表示i这种差值能被组合出来,差值有负数,所以用sum表示0,0表示-sum,2*sum表示sum。
询问X的时候,只需看dp[sum+X]或者dp[sum-X]是否有一个为1,注意RE。
#include<cstdio> #include<cstring> #include<cmath> #include<vector> #include<algorithm> #include<queue> using namespace std; int dp[8000]; int w[50]; int flag[8000]; int main() { int T,N,M; scanf("%d",&T); while(T--) { scanf("%d",&N); memset(dp,0,sizeof dp); for(int i=1;i<=N;i++) scanf("%d",&w[i]); int sum=0; for(int i=1;i<=N;i++) sum=sum+w[i]; dp[sum]=1; for(int i=1;i<=N;i++) { memset(flag,0,sizeof flag); for(int j=2*sum;j>=0;j--) { if(dp[j]) { if(j+w[i]<=2*sum) flag[j+w[i]]=1; if(j-w[i]>=0) flag[(j-w[i])]=1; } } for(int i=0;i<=2*sum;i++) if(flag[i]) dp[i]=1; } scanf("%d",&M); for(int i=1;i<=M;i++) { int x; scanf("%d",&x); if(x>sum||x<0) printf("NO "); else { if(dp[sum+x]==1||(sum-x>=0&&dp[sum-x]==1)) printf("YES "); else printf("NO "); } } } return 0; }