问题 D: 小李打怪兽(01背包)

时间限制: 1 Sec  内存限制: 128 MB
提交: 115  解决: 54
[提交] [状态] [讨论版] [命题人:外部导入]

题目描述

 小李对故乡的思念全部化作了对雾霾天气的怨念,这引起了掌控雾霾的邪神的极大不满,邪神派去了一只小怪兽去对付小李,由于这只怪兽拥有极高的IQ,它觉得直接消灭小李太没有难度了,它决定要和小李在智力水平上一较高下。我们可否帮助小李来战胜强大的怪兽呢? 

问题是这样的:给定一堆正整数,要求你分成两堆,两堆数的和分别为S1S2,谁分的方案使得 S1*S1-S2*S2的结果小(规定S1>=S2),谁就将获得胜利。 

注:S2可以等于0

输入

 

第一行n,表示共有n个数
第二行共n个用空格隔开的正整数ai,表示给定的一堆正整数。

输出

输出就一个整数,表示 S1*S1-S2*S2 的最小值。

样例输入

1 2 3 4 

样例输出

0

提示

 

14一堆,23一堆,5*5-5*5 = 0  

60%的数据,1<=n<=20

80%的数据,1<=n<=50ai<=20

100%的数据,1<=n<=100ai<=100


说实话我第一眼是排序贪心..然后分成两堆求,然后我自己举出了反例..这道题实际用01背包的知识点..我应该是最近在做线段树的模板题改模板和那种容易看出知识点的题做多了,变式题想不到相关知识点

先sort

s1*s1-s2*s2=(s1+s2)--(s1-s2),前面一个是总和。s1,s2,尽量往sum/2去靠,不妨令s2是小于sum/2的,然后在n个数去挑价值最大,每个数的价值同时是体积,背包的体积容量是sum/2.这时候,问题迎刃而解。

不妨总结一下,以后在碰到两边有一定关系的并且其中一边往某个边界靠的,试试01背包


#include<stdio.h>
#include<math.h>
#include<string.h>
#include<algorithm>
using namespace std;
//不一定平均分的 
int a[100000];
int dp[100000];
int n;
long int sum;

int main(void)
{
		while(scanf("%d", &n)!=EOF)
		{
			sum=0;
		 	for(int i=1;i<=n;i++)
			 {
			 	scanf("%d",&a[i]);sum+=a[i];	
			 }	
			
			int c=sum/2;
		
			for(int i=1;i<=n;i++)
			{
				for(int j=c;j>=a[i];j--)
				{
					dp[j]=max(dp[j],dp[j-a[i]]+a[i]);
				}
			}
				
		    printf("%d\n",sum*( (sum-dp[c])-dp[c] ) );
		
		}
return 0;
} 
发布了50 篇原创文章 · 获赞 6 · 访问量 1750

猜你喜欢

转载自blog.csdn.net/zstuyyyyccccbbbb/article/details/104110517