首页 > 代码库 > Knapsack I 竟然是贪心,证明啊。。。。
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
41 1 1 1 331 3 911
Sample Output
YESNO
直接贪心。就是现实生活中的找零钱,将输入从大到小排序, 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 }
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。