题目描述
有一天,他在宿舍里无意中发现了一个天平!这 个天平很奇怪,有n个完好的砝码,但是没有游码。盾神为他的发现兴奋不已!于是他准备去称一称自己的东西。他准备好了m种物品去称。神奇的是,盾神一早就 知道这m种物品的重量,他现在是想看看这个天平能不能称出这些物品出来。但是盾神稍微想了1秒钟以后就觉得这个问题太无聊了,于是就丢给了你。
数据规模和约定
1< =n< =24, 1< =m< =10.
输入
第一行为两个数,n和m。
第二行为n个数,表示这n个砝码的重量。
第三行为m个数,表示这m个物品的重量。
输出
输出m行,对于第i行,如果第i个物品能被称出,输出YES否则输出NO。
样例输入
4 2
1 2 4 8
15 16
样例输出
YES
NO
提示
C语言在线学习平台微信号dotcpp
来源
算法提高
使用动态规划是错误的方法,因为没有知道质量砝码质量的前提下不知道数组如何设置大小,所以大部分的数据都不能通过。
#include<iostream>
#include<algorithm>
using namespace std;
int m,n;
int A[30],w[11];
bool dp[1000][1000];
long long sum;
int main(void)
{
freopen("D:\\input2.txt","r",stdin);
cin>>n>>m;
for(int i=1;i<=n;i++) cin>>A[i];
for(int i=1;i<=m;i++) cin>>w[i];
for(int i=1;i<=n;i++) sum+=A[i];
cout<<"sum="<<sum<<endl;
dp[0][sum]=true;//表示可以使用0个砝码组成质量为0的组成
for(int i=1;i<=n;i++)//枚举n个物品
{
for(int j=0;j<=sum*2;j++)//枚举n个物品可能组成的质量
{
if(j>=A[i]) if(dp[i-1][j-A[i]]) dp[i][j]=true;//如果前i-1个砝码质量为j-A[i]那么可以组合成j
if(dp[i-1][j+A[i]]) dp[i][j]=true;//如果前i个可以组合成j+A[i],那么可以去掉这个砝码组成j
dp[i][j]=max(dp[i][j],dp[i-1][j]);//放置断层
}
}
/*
for(int i=1;i<=n;i++)
{
for(int j=0;j<=2*sum;j++)
{
printf("dp[%d][%d]=%d ",i,j,dp[i][j]);
}
printf("\n");
}
*/
for(int i=0;i<=sum*2;i++)
{
if(dp[n][i])
{
cout<<i-sum<<" ";
}
}
cout<<endl;
for(int i=1;i<=m;i++)
{
if(dp[n][sum-w[i]] || dp[n][sum+w[i]]) cout<<"YES"<<endl;
else cout<<"NO"<<endl;
}
return 0;
}