贪心并不难,难的是证明。

贪心并不难,难的是证明。 贪心并不难,难的是证明。 贪心并不难,难的是证明。
                                                                                                                                                     ———— heidoudou

基本思路:先将数组 s o r t sort sort一遍,然后用双指针i = 1j = n i f ( a i + a j > w ) if(a_i+a_j>w) if(ai+aj>w),则将 a j a_j aj单独分为一组,--j e l s e else else则将 a i a_i ai a j a_j aj分为一组,++i--j

证明:

  1. i f ( a i + a j > w ) if(a_i+a_j>w) if(ai+aj>w) a j a_j aj也不可能和其他任何一个 a k ( i < k < j ) a_k(i<k<j) ak(i<k<j)为一组 → \to a j a_j aj单独一组
  2. i f ( a i + a j ≤ w ) if(a_i+a_j≤w) if(ai+ajw){
            i f if if a i a_i ai a j a_j aj各为一组,那么就会比 a i a_i ai a j a_j aj为一组的情况多出一组;
            e l s e else else i f if if a i a_i ai单独一组, a j a_j aj与另一个 a k a_k ak为一组,那么 a j a_j aj a k & a i a_k\And a_i ak&ai的组数 = a j = a_j =aj a i & a k a_i\And a_k ai&ak的组数;
            e l s e else else i f if if a j a_j aj单独一组, a i a_i ai与另一个 a k a_k ak为一组,那么 a i a_i ai a k & a j a_k\And a_j ak&aj的组数 = a i = a_i =ai a j & a k a_j\And a_k aj&ak的组数;
            e l s e else else i f if if a i a_i ai a k a_k ak a j a_j aj a m a_m am为一组,交换 a k & a j a_k \And a_j ak&aj后,    ⟹    a i + a j ≤ w \implies a_i+a_j≤w ai+ajw a k + a m ≤ a k + a j ≤ w    ⟹    a_k+a_m≤a_k+a_j≤w \implies ak+amak+ajw
            a i a_i ai a k & a j a_k\And a_j ak&aj a m a_m am的组数 = a i = a_i =ai a j & a k a_j\And a_k aj&ak a m a_m am的组数;
    }
    ∴ ∴ 我们证明看子问题的最优解可以通过上述贪心过程得到

下面我们证明贪心后 ∑ ∑ 子问题的最优解就是全局最优解

a [ i . . . j ] a[i...j] a[i...j]问题为 P P P P P P的贪心解为 S S S,经过贪心之后, ∑ ∑ 子问题 P ′ P' P的最优解为 S ′ S' S。如果 ∑ ∑ 子问题 P ′ P' P的最优解 S ′ S' S不是 P P P的最优解,那么我们先假设存在一个最优解 Z Z Z,可以通过上述证明过程后,使之变成相同 ∑ ∑ 子问题 P ′ P' P的解 Z ′ Z' Z,又 ∵ S > Z ∵S>Z S>Z,而且二者贪心后的分组数是相同的, ∴ ∴ S ′ > Z ′ S'>Z' S>Z,这就与 S ′ S' S为最优解相矛盾, → ∑ \to∑ 子问题的最优解 = = = 全局最优解

证毕 . 证毕. 证毕.

光知道贪心,贪心为什么可以得到最优解,你证明过么? 光知道贪心,贪心为什么可以得到最优解,你证明过么? 光知道贪心,贪心为什么可以得到最优解,你证明过么?
                                                                                                                                                     ———— heidoudou

#include<bits/stdc++.h>
#define ll long long
#define maxn 30005
using namespace std;
inline int read(){
	int x = 0; bool f = false; char ch = getchar();
	while(!isdigit(ch)){if(ch == '-') f = true; ch = getchar();}
	while(isdigit(ch)){x = x * 10 + ch - '0'; ch = getchar();}
	return f ? -x : x;
}
inline void write(ll x){
	if (x < 0) x = ~x + 1, putchar('-');
	if (x > 9) write(x / 10);
	putchar(x % 10 + '0');
}
int w, n, p[maxn], ans;
int main(){
	w = read(); n = read();
	for(register int i = 1; i <= n; ++i) p[i] = read();
	sort(p + 1, p + n + 1);
	int i = 1, j = n;
	while(i <= j){
		if(p[i] + p[j] > w){++ans; --j;}
		else{++ans; ++i; --j;}
	}
	write(ans); puts("");
	return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值