Knapsack I 竟然是贪心,证明啊。。。。

Knapsack I

Time Limit: 2000/1000MS (Java/Others) Memory Limit: 128000/64000KB (Java/Others)

SubmitStatus

Problem Description

给出N个数a[1]....a[N],对于任意两个数(a[i],a[j]),保证a[i] % a[j] == 0 || a[j] % a[i] == 0,再给出一个数M,问这些数能否取出若干个来,使得其和为M

Input

多组数据,每组数组首先输入N,然后接下来有N个数a[1] ... a[N],然后输入M,含义如题目描述

1 <= N <= 24, 1 <= a[i],M <= 10000000

Output

每组数据,输出一行,如果可以组成M,输出"YES",否则输出"NO".

Sample Input

4
1 1 1 1
3
3
1 3 9
11

Sample Output

YES
NO

直接贪心。就是现实生活中的找零钱,将输入从大到小排序, for(int i = 1; i <= n; i ++)
if(m >= a[i]) m -= a[i];
if(!m) YES; else NO
证明:不妨设存在合法方案 m = c1 + c2 + .. ck(c1 <= c2 <= ... <= ck)
假设你现在要用一个更大的数 X 去取代部分数
求出最小的 i,使得 c1 + c2 + ... + ci >= X,c1 + c2 + ... + c[i - 1] < X
尝试去掉 c1,如果 c2 + ... + ci >= X,最后剩下的串为 cj + ... + ci >= X,且 c[j + 1] + .. + ci < X,(否则继续去掉 cj)
如果 cj > X,那么 X 一定不能被替换了。
否则,因为 cj + 1 % cj = 0.. c[i] % c[i - 1] == 0,且 X >= c[j], X % c[j] = 0
设 cj + .. + ci = k1 * cj  X = k2 * cj,  cj + 1 + .. + ci = k3 * cj
k1 >= k2 > k3,
所以 k2 >= k3 + 1 因为 k1 - k3 == 1,只差一个 cj
所以 k2 = k1,因此可以直接用 X 替换掉 cj + .. + ci

 1 #include <iostream>
 2 #include <stdio.h>
 3 #include <algorithm>
 4 #include <string.h>
 5 using namespace std;
 6
 7 int main()
 8 {
 9     int n,m,i,j,a[30];
10     while(scanf("%d",&n)!=EOF)
11     {
12         for(i=0;i<n;i++)scanf("%d",&a[i]);
13         scanf("%d",&m);
14         sort(a,a+n);
15         for(i=n-1;i>=0;i--)
16         {
17             if(m>=a[i])
18             m-=a[i];
19         }
20         if(m)
21         printf("NO\n");
22         else printf("YES\n");
23     }
24
25 }

Knapsack I 竟然是贪心,证明啊。。。。

时间: 2024-10-15 19:21:55

Knapsack I 竟然是贪心,证明啊。。。。的相关文章

HDU 4923 (贪心+证明)

Room and Moor Problem Description PM Room defines a sequence A = {A1, A2,..., AN}, each of which is either 0 or 1. In order to beat him, programmer Moor has to construct another sequence B = {B1, B2,... , BN} of the same length, which satisfies that:

贪心专题

贪心: 原则是根据固定的一个或几个属性进行抉择.达到缩小规模的目的. split to steps and shrink scope 有点双端/DAG图的意思. reference 最近做的几个贪心题目 hdu 1052(田忌赛马) 根据马的速度排序,然后两边最小值,最大值的判断.这样做是因为两端的选择是唯一的,TJ最弱的马/最强的如果可以战胜那就是最好的抉择,不然就让其去当炮灰.(减少规模) #include<set> #include<cmath> #include<cs

[贪心][高精]P1080 国王游戏(整合)

题目描述 恰逢 H 国国庆,国王邀请 n 位大臣来玩一个有奖游戏.首先,他让每个大臣在左.右手上面分别写下一个整数,国王自己也在左.右手上各写一个整数.然后,让这 n 位大臣排成一排,国王站在队伍的最前面.排好队后,所有的大臣都会获得国王奖赏的若干金币,每位大臣获得的金币数分别是:排在该大臣前面的所有人的左手上的数的乘积除以他自己右手上的数,然后向下取整得到的结果. 国王不希望某一个大臣获得特别多的奖赏,所以他想请你帮他重新安排一下队伍的顺序,使得获得奖赏最多的大臣,所获奖赏尽可能的少.注意,国

[贪心][高精度][NOIP]国王游戏

题目梗概 有n个大臣,他们可以拿到他们之前所有人左手数的乘积除以他的右手,问是否能通过调换位置来使拿钱最多的大臣拿的钱最少. 思考 贪心证明: 设相邻的两个人$i, i + 1$.设$A[i] \times B[i] \leqslant  A[i + 1] B[i + 1]$,i之前所有人的左手乘积为S. 则,$ans1 = max \left (\frac{S}{B[i]} , \frac{S}{A[i] \times B[i+1]}  \right )$ 若交换 $ans2 = max \l

bzoj 1664 (贪心)

[Usaco2006 Open]County Fair Events 参加节日庆祝 Time Limit: 5 Sec  Memory Limit: 64 MBSubmit: 487  Solved: 344[Submit][Status][Discuss] Description Farmer John has returned to the County Fair so he can attend the special events (concerts, rodeos, cooking s

三类基于贪心思想的区间覆盖问题

一.区间完全覆盖问题 问题描述:给定一个长度为m的区间,再给出n条线段的起点和终点(注意这里是闭区间),求最少使用多少条线段可以将整个区间完全覆盖. 样例:一个长度为8的区间,可选的线段有[2,6],[1,4],[3,6],[3,7],[6,8],[2,4],[3,5]. 求解过程: 1.将每一条线段按左端点递增顺序排列,如果左端点相同,按右端点递增顺序排列,排完序后为[1,4],[2,4],[2,6],[3,5],[3,6],[3,7],[6,8]: 2.设置一个变量表示已覆盖到的区间右端点,

浅谈贪心

序言 贪心算法是 \(\text{OI}\) 界中一门高深又基础的算法,一般用于求解最优性问题. 贪心变化多端,时易时难,例如:易的 删数问题 ,难的 树上的数 . 博主因为学业繁忙,只能抽出时间写,经常会咕咕咕,写的不好的请见谅. 参考文献:李煜东<算法竞赛进阶指南>. \(~\) 贪心是个啥? 贪心贪心,当然是贪心啦. 贪心是一种在每一次做决策的时候,总是采取当前意义下最优策略的算法. 换句话说,每次做出选择,我们总是会选择当前看来最优秀的选择. 这是一种 局部最优性 推导至 整体最优性

图论-最小生成树

今天听了CLRS的第二作者讲的课程,关于最小生成树的算法. 其实就是先模拟一下小样例(不是单纯模拟,而是发现其中的规律,要思考) 然后发现最优子结构-如果(u,v)是一条唯一连接两点的边,那么将原图拆分为两块(一块包含u,一块包含v),两图分别最优解+dist[u,v]就是原图的最优解了. 然后发现这样做会有很多很多的重叠子问题:把每次的(u,v)换一换顺序就一堆重叠子问题.于是就有动态规划的思路了-- 别急! 这里还有一个性质:如果(u,v)在当前图中边权最小,则(u,v)必在此图的最小生成树

NOIP2013积木大赛

今天咱家心情好,去2013年的题看了看,不幸的遇到了一道水题 题目简述:给你一个长度为n的目标序列,你每次可以把某一个区间中所有的值加一,问最少需要多少次操作才可以把一个长度为n的0序列变成目标序列 来看看这家伙,区间修改!我直接无脑打了个线段树模板,然而发现卵用没有,虽然网上有一些题解是贪心+线段树的,然而我们不需要线段树也可以直接贪到100分,而且要比线段树快,因为我们是O n 做的 咱家不会贪心证明,咱家只能在这跟你们瞎咧咧几句咱家的理解:每次只能+1 ,这是一个很好的性质,然后我们来想想