题目链接
https://www.qduoj.com/problem/93
题目大意
判断是否能将一组数平均分成两份。
解题思路
一看到这个题感觉好像做过,但还是没做出来。
我成功的当成贪心去算了,wa不停。
正解是01背包恰好装满:
找个sum/2的背包,sum为数和。
每件物品的是每个数,每个数的值既是体积大小,又是自身价值。
最后只要看dp[sum/2]是否等于sum/2就行,这意味着sum/2大小的背包装下了价值为sum/2的东西。
对应到本题而言,意味着存在一组数的和正好为sum/2。
错误的贪心代码(我的)
#include<bits/stdc++.h> using namespace std; const int N=205; int a[N]; int sum1,sum2; int n; bool cmp(int x,int y){ return x>y; } int main(){ while(cin>>n){ sum1=0;sum2=0; for(int i=1;i<=n;i++) cin>>a[i]; sort(a+1,a+n+1,cmp); for(int i=1;i<=n;i++) sum1>sum2 ? sum2+=a[i] : sum1+=a[i]; cout<<(sum1==sum2 ? "YES" : "NO")<<endl; } } //反例:5 4 3 2 2
AC代码
#include<bits/stdc++.h> using namespace std; const int N=205; const int M=N*100; int dp[M]; int n,sum; int a[N]; int main(){ while(cin>>n){ sum=0; for(int i=1;i<=n;i++){ cin>>a[i]; sum+=a[i]; } if(sum&1){cout<<"NO"<<endl;}//判断为奇数 else{ memset(dp,0,sizeof dp);//勿忘 sum/=2; for(int i=1;i<=n;i++) for(int j=sum;j>=a[i];j--) dp[j]=max(dp[j-a[i]]+a[i],dp[j]); if(dp[sum]==sum)cout<<"YES"<<endl; else cout<<"NO"<<endl; } } }
总结
感觉很简单一道题,而且好像还做过类似的,还是没做出来,我真的菜的抠jio。
还是要记住这种方法!!!
最后的最后,我还想再问上天一句:我什么时候才能成为大佬啊啊啊!!!