nyoj郵票分你一半


 描述 小珂最近收集了些郵票,他想把其中的一些給他的好朋友小明。每張郵票上都有分值,他們想把這些郵票分成兩份,並且使這兩份郵票的分值和相差最小(就是小珂得到的郵票分值和與小明的差值最小),現在每張郵票的分值已經知道了,他們已經分好了,你知道最後他們得到的郵票分值和相差多少嗎?
輸入
第一行只有一個整數m(m<=1000),表示測試數據組數。
接下來有一個整數n(n<=1000),表示郵票的張數。
然後有n個整數Vi(Vi<=100),表示第i張郵票的分值。
輸出
輸出差值,每組輸出佔一行。
樣例輸入
2
5
2 6 5 8 9
3
2 1 5
樣例輸出
0
2
相同的套路,轉化爲01揹包問題。如果不能均分就儘量使兩堆重量/票價差距最小。可以想象成有一堆物品,兩個容器(容量和除以2),只要保證把其中一個容器的容積儘量加滿(當然恰好能滿最好),這就轉化成了0,1揹包問題了。
狀態轉移方程:dp[j] = max(dp[j],dp[j-weight[i]]+c[i]);
本題可以結合下一篇zb的生日http://blog.csdn.net/yjl1511/article/details/77365972
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int dp[100005];
int a[1005];
int main()
{
	int m,n,i,j;
	scanf("%d",&m);
	while(m--)
	{
		memset(dp,0,sizeof(dp));
		memset(a,0,sizeof(a));
		scanf("%d",&n);
		int sum=0;
		for(i=1;i<=n;i++){
			scanf("%d",&a[i]);
			sum+=a[i];
		}
		int v=sum/2;
		for(i=1;i<=n;i++)
		for(j=v;j>=a[i];j--){
			dp[j]=max(dp[j],dp[j-a[i]]+a[i]);
		}
		printf("%d\n",sum-2*dp[v]);
		return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章