贪心算法的基本思路是从问题的某一个初始解出发一步一步地进行,根据某个优化测度,每一步都要确保能获得局部最优解。每一步只考虑一个数据,他的选取应该满足局部优化的条件。若下一个数据和部分最优解连在一起不再是可行解时,就不把该数据添加到部分解中,直到把所有数据枚举完,或者不能再添加算法停止
值得注意的是贪心算法需要证明后才能真正运用到题目的算法中。贪心算法的证明围绕着:整个问题的最优解一定由在贪心策略中存在的子问题的最优解得来的。
下面是一个比较简单的贪心算法的案例
Problem Description
FatMouse prepared M pounds of cat food, ready to trade with the cats guarding the warehouse containing his favorite food, JavaBean.
The warehouse has N rooms. The i-th room contains J[i] pounds of JavaBeans and requires F[i] pounds of cat food. FatMouse does not have to trade for all the JavaBeans in the room, instead, he may get J[i]* a% pounds of JavaBeans if he pays F[i]* a% pounds of cat food. Here a is a real number. Now he is assigning this homework to you: tell him the maximum amount of JavaBeans he can obtain.
The warehouse has N rooms. The i-th room contains J[i] pounds of JavaBeans and requires F[i] pounds of cat food. FatMouse does not have to trade for all the JavaBeans in the room, instead, he may get J[i]* a% pounds of JavaBeans if he pays F[i]* a% pounds of cat food. Here a is a real number. Now he is assigning this homework to you: tell him the maximum amount of JavaBeans he can obtain.
Input
The input consists of multiple test cases. Each test case begins with a line containing two non-negative integers M and N. Then N lines follow, each contains two non-negative integers J[i] and F[i] respectively. The last test case is followed by two -1's. All integers are not greater than 1000.
Output
For each test case, print in a single line a real number accurate up to 3 decimal places, which is the maximum amount of JavaBeans that FatMouse can obtain.
Sample Input
5 3
7 2
4 3
5 2
20 3
25 18
24 15
15 10
-1 -1
Sample Output
13.333
31.500
这道题的做法是先对性价比进行排序,每一步选择性价比高的商品
1 #include<stdio.h> 2 #include<stdlib.h> 3 #include<string.h> 4 typedef struct Goods 5 { 6 double weight; //重量 7 double price; //价格 8 double cost; //性价比 9 10 } Goods; 11 Goods g[1002]; 12 13 int cmp( const void *a,const void *b); 14 15 int main() 16 { 17 int n; 18 double m,ret; 19 int i; 20 int index = 0; //货物下标 21 22 while( scanf("%lf%d",&m,&n)!=EOF) 23 { 24 if( m==-1 && n==-1) break; 25 26 for( i=0 ; i<n; i++) 27 { 28 scanf("%lf%lf",&g[i].weight,&g[i].price); 29 g[i].cost = g[i].weight/g[i].price; 30 } 31 32 qsort( g,n,sizeof( g[0]),cmp); //对性价比进行降序排序 33 while( m>0 && index<n) 34 { 35 if( m > g[index].price) 36 { 37 //钱够买下全部物品 38 ret += g[index].weight; 39 m -= g[index].price; 40 } 41 else 42 { 43 //只能买下部分物品 44 ret += g[index].weight * m / g[index].price; 45 m = 0; 46 } 47 index ++; 48 } 49 printf("%.3lf ",ret); 50 51 } 52 return 0; 53 } 54 55 int cmp( const void *a,const void *b) 56 { 57 Goods *c = (Goods *)a; 58 Goods *d = (Goods *)b; 59 return (d->cost > c->cost) ? 1:-1; 60 }
下面这道题用贪心算法也很快
- 题目描述:
-
通过悬崖的yifenfei,又面临着幽谷的考验——
幽谷周围瘴气弥漫,静的可怕,隐约可见地上堆满了骷髅。由于此处长年不见天日,导致空气中布满了毒素,一旦吸入体内,便会全身溃烂而死。
幸好yifenfei早有防备,提前备好了解药材料(各种浓度的万能药水)。现在只需按照配置成不同比例的浓度。
现已知yifenfei随身携带有n种浓度的万能药水,体积V都相同,浓度则分别为Pi%。并且知道,针对当时幽谷的瘴气情况,只需选择部分或者全部的万能药水,然后配置出浓度不大于 W%的药水即可解毒。
现在的问题是:如何配置此药,能得到最大体积的当前可用的解药呢?
特别说明:由于幽谷内设备的限制,只允许把一种已有的药全部混入另一种之中(即:不能出现对一种药只取它的一部分这样的操作)。
- 输入:
-
输入数据的第一行是一个整数C,表示测试数据的组数;
每组测试数据包含2行,首先一行给出三个正整数n,V,W(1<=n,V,W<=100);
接着一行是n个整数,表示n种药水的浓度Pi%(1<=Pi<=100)。
- 输出:
-
对于每组测试数据,请输出一个整数和一个浮点数;
其中整数表示解药的最大体积,浮点数表示解药的浓度(四舍五入保留2位小数);
如果不能配出满足要求的的解药,则请输出0 0.00。
- 样例输入:
-
3 1 100 10 100 2 100 24 20 30 3 100 24 20 20 30
- 样例输出:
-
0 0.00 100 0.20 300 0.23
这道题的做法是将各药剂的浓度进行排序,如果浓度最低的都比预定的浓度高则无法配出。否则逐步选择浓度低的药剂混合1 #include<stdio.h> 2 #include<stdlib.h> 3 #include<string.h> 4 5 int potion[1002]; //药剂浓度 6 7 int cmp( const void *a, const void *b); 8 int main() 9 { 10 int c,n,v,w; 11 int j; 12 int ansv; 13 double ansn; 14 while( scanf("%d",&c) != EOF) 15 { 16 while( c--) 17 { 18 scanf("%d %d %d",&n,&v,&w); 19 for( j=0; j<n; j++) 20 { 21 scanf("%d",&potion[j]); 22 } 23 qsort( potion, n, sizeof( potion[0]),cmp);//对药剂浓度从小到大排序 24 if( potion[0] > w) 25 { 26 ansv = 0; //目标体积 27 ansn = 0.00; //目标浓度 28 } 29 else 30 { 31 ansv =v; 32 ansn = potion[0]; 33 for( j=1; j<n ; j++) 34 { 35 if( (ansv*ansn+v*potion[j]) <= (ansv+v)*w) 36 { 37 //如果相加后的浓度小于预定浓度 38 ansv += v; 39 ansn = 1.0*((ansv-v)*ansn+v*potion[j])/ansv; 40 } 41 } 42 43 } 44 printf("%d %.2lf",ansv,ansn/100); 45 46 } 47 } 48 return 0; 49 } 50 51 int cmp( const void *a,const void *b) 52 { 53 54 return *(int *)a - *(int *)b; //从小到大排序 55 }