1 2 1 4 3 2 4 5
NO YES YESHintFor the Case 1:Put the 4 weight alone For the Case 2:Put the 4 weight and 1 weight on both side
因为N不大,并且wi也不大,我们这里可以应用数组标记的方法,暴力枚举出每一种可能。
首先我们需要两个vis数组 。我们这里规定1代表有这个可能,0代表没有这个可能、这里对应核心代码详解:
并且这里要注意,题干中样例如果加一个3的话,也是应该输出YES的~
memset(vis1,0,sizeof(vis1)); memset(vis2,0,sizeof(vis2)); vis1[0]=1;//0是一定可以称出来的 for(int i=1;i<=n;i++) { for(int j=0;j<=2000;j++)//20*100是最大的边界 { if(vis1[j]!=0)//如果vis1数组上标记过这个数。 { vis2[j]=1; vis2[j+a[i]]=1;//处理+ vis2[abs(j-a[i])]=1;//处理- } } for(int k=0;k<=2000;k++)//数组赋值过去 { vis1[k]=vis2[k]; vis2[k]=0; } }
蓝后是完整的AC代码:
#include<stdio.h> #include<math.h> #include<string.h> #include<stdlib.h> using namespace std; int vis1[2005]; int vis2[2005]; int a[2005]; int main() { int t; scanf("%d",&t); while(t--) { int n; scanf("%d",&n); for(int i=1;i<=n;i++) { scanf("%d",&a[i]); } memset(vis1,0,sizeof(vis1)); memset(vis2,0,sizeof(vis2)); vis1[0]=1; for(int i=1;i<=n;i++) { for(int j=0;j<=2000;j++) { if(vis1[j]!=0) { vis2[j]=1; vis2[j+a[i]]=1; vis2[abs(j-a[i])]=1; } } for(int k=0;k<=2000;k++) { vis1[k]=vis2[k]; vis2[k]=0; } } int m; scanf("%d",&m); while(m--) { long long int q; scanf("%I64d",&q); if(vis1[q]==0||q<0||q>2000) { printf("NO\n"); } else { printf("YES\n"); } } } }