【题目链接】
ybt 1939:【07NOIP普及组】纪念品分组
洛谷 P1094 [NOIP2007 普及组] 纪念品分组
【题目考点】
1. 贪心
【解题思路】
贪心选择:选择价格最小的和最大的纪念品分成一组,若价格最小的和最大的纪念品无法
分成一组,那么价格最大的纪念品单独一组。
将问题抽象为:有n个数字,要凑成加和小于等于w的组,一组可以有2个数或1个数,最少可以凑多少组。
1. 贪心选择性质的证明:
贪心选择:
如果最大值加最小值大于w,那么最大值单独一组。
如果最大值加最小值小于等于w,最大最小值凑成一组。
- 证明:存在最优解包含第一次贪心选择
如果第一次选择的组只有最大值,由于最大值无法和其他数字凑成一组,最大值单独一组是唯一的选择。
如果第一次的贪心选择是最大最小值构成的一组。设最大值为 l l l,最小值为 g g g,那么一定有: l + g ≤ w l+g\le w l+g≤w
假设对于所有最优解,都不包含第一次的贪心选择,也就是说 l l l和 g g g不会分为一组。
l l l可以有以下几种情况
- l l l单独一组:无论 g g g与另一个数字一组,还是 g g g单独一组,都可以让 g g g更改为与 l l l一组。
- l l l与另一个数字 x x x一组,那么有 l + x ≤ w l+x\le w l+x≤w。
假设此时 g g g单独一组,那么可以让 g g g与 x x x交换,得到 l l l与 g g g一组。
假设此时 g g g与另一个数字 h h h一组,那么有 h + g ≤ w h+g\le w h+g≤w
由于 l l l是当时的最大值,那么一定有 h ≤ l h\le l h≤l,所以有 h + x ≤ l + x ≤ w h+x\le l+x\le w h+x≤l+x≤w, h h h与 x x x一组加和并不会超过 w w w。 将 g g g与 x x x交换, l l l与 g g g一组, h h h与 x x x一组,是可行的。
无论什么情况,都可以通过交换使得 l l l与 g g g一组,这样做分组数量不会增加,该方案仍然是最优解,最优解中包含了贪心选择,与假设相悖,原命题得证。
- 证明:进行k次贪心选择后,存在最优解包含第k+1次的贪心选择。
证明方法与证明第1点相似,不再赘述。
2.具体做法:
对所有纪念品按升序排序,设l,r两个指针指向当前看到的价格最小和最大的纪念品。
- 如果第l和第r个纪念品的价格加和大于w,那么第l纪念品单独一组,l加1。
- 如果第l和第r个纪念品的价格加和小于等于w,那么第l和第r纪念品分为一组,l和r都加1。
【题解代码】
解法1:贪心
#include<bits/stdc++.h>
using namespace std;
#define N 30005
int main()
{
int p[N], w, n, ct = 0;//ct:组数
cin >> w >> n;
for(int i = 1; i <= n; ++i)
cin >> p[i];
sort(p+1, p+1+n);
int l = 1, r = n;
while(l <= r)
{
if(l != r && p[l] + p[r] <= w)
{
l++;
r--;
ct++;//l, r凑一组
}
else
{
r--;
ct++;//r自己凑一组
}
}
cout << ct;
return 0;
}