chapter 4:贪心
贪心搞了5天的时间。。。。略坑。贪心呢,其实就是一种思想,在对问题求解时,总是作出在当前看来是最好的选择。也就是说,不从整体上加以考虑,它所作出的仅仅是在某种意义上的局部最优解(是否是全局最优,需要证明)。其实贪心用的最多的东西就是快排,我感觉做的每题都用到了快排,有的也用到了结构体。
1.HDOJ 1009 FatMouse' Trade
这一题是说catfood与javabean之间可以互换,然后找最多可以换多少个javabean。这就与交换率有关了,优先满足交换率高的,肯定得到的javabean就多 了。用结构体记录,然后快排即可。
1 #include<cstdio> 2 #include<cstring> 3 #include<cstdlib> 4 #include<cmath> 5 #include<algorithm> 6 using namespace std; 7 struct node{ 8 int k; 9 int i; 10 double bili; 11 }cat[1001]; 12 int cmp(node a,node b){ 13 return a.bili>b.bili; 14 } 15 int main(){ 16 int n,m; 17 while(scanf("%d%d",&m,&n)&&(m!=(-1))){ 18 int f,j; 19 for(int i=0;i<n;i++){ 20 scanf("%d%d",&j,&f); 21 cat[i].bili=(double)j/(double)f; 22 cat[i].i=f; 23 cat[i].k=j; 24 } 25 sort(cat,cat+n,cmp); 26 double temp=(double)m; 27 double ans=0; 28 for(int i=0;i<n;i++){ 29 //printf("%d %.2lf\n",cat[i].i,cat[i].bili); 30 if(temp>=(double)cat[i].i){ 31 temp-=(double)cat[i].i; 32 ans+=(double)cat[i].k; 33 //printf("%.3lf\n",temp); 34 } 35 else{ 36 ans+=temp*cat[i].bili; 37 //printf("%.3lf\n",temp); 38 break; 39 } 40 } 41 printf("%.3lf\n",ans); 42 } 43 return 0; 44 }
2.HDOJ 1050 Moving Tables
这题的基本解法:初始化数组,如果需要移动,自增一,代表一个操作,最后便历,找出操作数做多的那个,就是我们需要的最长时间。
1 #include <iostream> 2 #include <cmath> 3 using namespace std; 4 int p[205]; 5 int main() 6 { 7 int T , n , s ,d , t,min , temp; 8 cin >> T; 9 while(T--) 10 { 11 12 for(int j = 0; j < 200 ; j++) 13 { 14 p[j] = 0; 15 } 16 cin >> t; 17 for(int j= 0 ; j < t ; j++) 18 { 19 cin >> s >> d; 20 s = (s - 1) / 2;//奇偶对门 21 d = (d - 1) / 2; 22 if(s > d) 23 { 24 temp = s; 25 s = d ; 26 d = temp; 27 } 28 for(int k = s ; k <= d; k++) 29 { 30 p[k] ++; 31 } 32 33 } 34 int max = -1; 35 for(int j = 0 ; j < 200 ; j++)//找出用得最多的那个 36 { 37 if(p[j] > max)max = p[j]; 38 } 39 cout << max * 10 <<endl; 40 41 } 42 return 0; 43 }
3.HDOJ 2037 今年暑假不AC
这个题就是一个安排时间表的题,有很多电视节目,然后告诉你开始时间和结束时间,问你最多能安排多少个节目。我们可以先对电视节目结束的时间进行排序,然后,向前找不冲突最多的电视节目个数就行。
1 #include<cstdio> 2 #include<cstring> 3 #include<cstdlib> 4 #include<cmath> 5 #include<algorithm> 6 using namespace std; 7 struct jiemu{ 8 int start; 9 int end; 10 int length; 11 }ti[101]; 12 int cmp(jiemu a,jiemu b){ 13 return a.end<b.end; 14 } 15 int main(){ 16 int n; 17 while(scanf("%d",&n)&&n!=0){ 18 int ti_s,ti_e; 19 for(int i=0;i<n;i++){ 20 scanf("%d%d",&ti_s,&ti_e); 21 ti[i].start=ti_s; 22 ti[i].end=ti_e; 23 ti[i].length=ti_e-ti_s; 24 } 25 sort(ti,ti+n,cmp); 26 int ans=0,temp=ti[0].start; 27 for(int i=0;i<n;i++){ 28 if(ti[i].start>=temp){ 29 ans++; 30 temp=ti[i].end; 31 } 32 } 33 printf("%d\n",ans); 34 } 35 return 0; 36 }
4.HDOJ 1051 Wooden Sticks
题目意思是让你求操作的时间,开机需要1分钟,然后如果后一个的长度或质量比前一个小的话需要调整,需要1分钟,求安排的最少时间。我们排序的时候就可以依据那个要求排序,先按长度的由小到大排序,如果长度相等就按质量由小到大排序。
1 #include<cstdio> 2 #include<cstring> 3 #include<cstdlib> 4 #include<cmath> 5 #include<algorithm> 6 using namespace std; 7 8 struct sticks{ 9 int length; 10 int weigth; 11 int flag; 12 }arr[5001]; 13 14 int cmp(sticks a,sticks b){ 15 if(a.length!=b.length) return a.length<b.length; 16 else return a.weigth<b.weigth; 17 18 } 19 int main(){ 20 int t; 21 scanf("%d",&t); 22 while(t--){ 23 int n; 24 scanf("%d",&n); 25 for(int i=0;i<n;i++){ 26 scanf("%d%d",&arr[i].length,&arr[i].weigth); 27 arr[i].flag=0; 28 } 29 sort(arr,arr+n,cmp); 30 int temp,ans=0; 31 for(int i=0;i<n;i++){ 32 if(arr[i].flag==0){ 33 arr[i].flag=1; 34 temp=arr[i].weigth; 35 for(int j=i+1;j<n;j++){ 36 if(arr[j].flag==0&&arr[j].weigth>=temp){ 37 temp=arr[j].weigth; 38 arr[j].flag=1; 39 } 40 } 41 ans++; 42 } 43 } 44 printf("%d\n",ans); 45 } 46 return 0; 47 }
5.HDOJ 2545 Degree Sequence of Graph G
一句话,顶点的度序列 Havel 定理~
定义:给出一个无向图的顶点度序列 {dn},要求判断能否构造出一个简单无向图。
分析:
贪心的方法是每次把顶点按度大小从大到小排序,取出度最大的点Vi,依次和度较大的那些顶点Vj连接,同时减去Vj的度。连接完之后就不再考虑Vi了,剩下的点再次排序然后找度最大的去连接……这样就可以构造出一个可行解。
判断无解有两个地方,若某次选出的Vi的度比剩下的顶点还多,则无解;若某次Vj的度减成了负数,则无解。
至于什么是Havel定理,上面这个构造过程就是了~(转自别人的博客。。。。)。
1 #include<cstdio> 2 #include<cstring> 3 #include<cstdlib> 4 #include<algorithm> 5 using namespace std; 6 int d[1002]; 7 bool gr(int a,int b) 8 { 9 return a>b; 10 } 11 int main() 12 { 13 int t,n; 14 scanf("%d",&t); 15 while(t--){ 16 scanf("%d",&n); 17 memset(d,0,sizeof(d)); 18 for(int i=0;i<n;i++) 19 scanf("%d",&d[i]); 20 sort(d,d+n,gr); 21 int g=0; 22 while(d[0]!=0){ 23 for(int k=1;k<=d[0];k++){ 24 d[k]--; 25 if(d[k]<0){ 26 printf("no\n"); 27 g=1; 28 break; 29 } 30 } 31 d[0]=0; 32 sort(d,d+n,gr); 33 if(g==1) 34 break; 35 } 36 if(g==0) 37 printf("yes\n"); 38 39 } 40 return 0; 41 }
6.HDOJ 1052 Tian Ji -- The Horse Racing
田忌赛马,求他的最优解。其实我觉得这题像模拟,因为题目已经把怎么选马告诉你了。
1 #include<cstdio> 2 #include<cstring> 3 #include<cstdlib> 4 #include<cmath> 5 #include<algorithm> 6 using namespace std; 7 int arr1[1001],arr2[1001]; 8 int cmp ( const void *a , const void *b ) 9 { 10 return *(int *)a - *(int *)b; 11 } 12 int main(){ 13 int n; 14 while(scanf("%d",&n)&&n!=0){ 15 for(int i=0;i<n;i++) 16 scanf("%d",&arr1[i]); 17 for(int i=0;i<n;i++) 18 scanf("%d",&arr2[i]); 19 qsort(arr1,n,sizeof(int),cmp); 20 qsort(arr2,n,sizeof(int),cmp); 21 int begin1=0,begin2=0,ans=0,end1=n-1,end2=n-1; 22 while(begin1<=end1){ 23 if(arr1[begin1]>arr2[begin2]){ 24 begin1++; 25 begin2++; 26 ans++; 27 continue; 28 } 29 if(arr1[end1]>arr2[end2]){ 30 end1--; 31 end2--; 32 ans++; 33 continue; 34 } 35 if(arr1[begin1]<arr2[end2]){ 36 ans--; 37 } 38 begin1++; 39 end2--; 40 } 41 printf("%d\n",ans*200); 42 } 43 return 0; 44 }