赞
踩
贪心并不难,难的是证明。
贪心并不难,难的是证明。
贪心并不难,难的是证明。
———— heidoudou
基本思路:先将数组
s
o
r
t
sort
sort一遍,然后用双指针i = 1
,j = 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
证明:
下面我们证明贪心后 ∑ ∑ ∑子问题的最优解就是全局最优解
设 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; }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。