题目描述
m个小学生在一起做游戏。这些同学分别来自n个不同的学校。现在要进行这样一个非常好玩的游戏,首先要把同学们分成若干组,每组两个同学,并且每个组中的同学来自不同的学校,剩下的同学不能加入游戏。现在,我们要使剩下不能参加游戏的同学最少。请你帮忙求出最多能组成多少组学生玩游戏。
输入
两行 第一行:n m n个不同的学校,m个小学生
第二行:a1 a2 a3 …an
输出
一个整数,表示最多多少组学生玩游戏
样例输入
样例输入1
3 9
2 4 3
样例输入2
3 11
2 6 3
样例输出
样例输出1
4
样例输出2
5
数据范围限制
N<=100000,m<=1000000
这一题有两种做法,一种是数学方法,第二种是用DP来做。两种方法都能拿满分。
数学方法
我们定义ax值用来存a数组里的最大值,判断如果最大值与总和的差比最大值要大,就输出总和整除2的结果,否则判断如果最大值与总和的差是否比最大值要小,输出最大值与总和的差。
核心代码
if(m-ax>ax)
{
printf("%d",m/2);//最大值与总和的差比最大值要大
}
else if(m-ax<ax)
{
printf("%d",m-ax);//最大值与总和的差比最大值要小
}
DP方法
f[i]表示i*2个人最多多少组学生玩游戏。
第一层循环枚举1~n,第二层循环枚举m/2到第i个学校的人数。
如果f[j-a[i]]]+a[i]大于f[j]那么f[j]赋值为f[j-a[i]]+a[i]。
动态转移方程就是if(f[j-a[i]]+a[i]>f[j])f[j]=f[j-a[i]]+a[i];
核心代码
for(int i=1;i<=n;i++)
{
for(int j=s/2;j>=a[i];j--)
{
if(f[j-a[i]]+a[i]>f[j])
f[j]=f[j-a[i]]+a[i];
}
}
代码信息
方法一
时间复杂度 | 总时间 |
---|---|
Θ(n) | n |
方法二
时间复杂度 | 总时间 |
---|---|
Θ(nm) | n(m/2-a[i]) |