贪心专题16题

贪心题目:

1001

部分背包问题。优先选取性价比高的,将单位价格进行排序,依次选取,直至满足条件。

[cpp]  view plain copy
  1. #include<iostream>  
  2. #include<cstdio>  
  3. #include<cstring>  
  4. #include<algorithm>  
  5. using namespace std;  
  6. struct Node{  
  7.     int j,f;  
  8.     double p;  
  9. }a[1000];  
  10. int n,m;  
  11. bool cmp(Node n1,Node n2){  
  12.     return n1.p>n2.p;  
  13. }  
  14. int main(){  
  15.     while(scanf("%d%d",&n,&m)!=EOF&&(n!=-1&&m!=-1)){  
  16.         for(int i=0;i<m;i++){  
  17.             scanf("%d%d",&a[i].j,&a[i].f);  
  18.             a[i].p=a[i].j*1.0/a[i].f;  
  19.         }  
  20.         sort(a,a+m,cmp);  
  21.         double ans=0;  
  22.         int tmp=0;  
  23.         for(int i=0;i<m;i++){  
  24.             if(a[i].f+tmp>=n){  
  25.                 if(a[i].f+tmp==n)  
  26.                     ans+=a[i].j;  
  27.                 else  
  28.                     ans+=a[i].p*(n-tmp);  
  29.                 break;  
  30.             }  
  31.             else{  
  32.                 ans+=a[i].j;  
  33.                 tmp+=a[i].f;  
  34.             }  
  35.         }  
  36.         printf("%.3f\n",ans);  
  37.     }  
  38.     return 0;  
  39. }  


1002

没有交叉的区间是可以同时进行的。那么需要的次数便是某个点所经过的最大次数。

[cpp]  view plain copy
  1. #include<iostream>  
  2. #include<cstdio>  
  3. #include<cstring>  
  4. #include<algorithm>  
  5. using namespace std;  
  6. int t,n,x,y,a[205];  
  7. int main(){  
  8.     scanf("%d",&t);  
  9.     while(t--){  
  10.         scanf("%d",&n);  
  11.         memset(a,0,sizeof(a));  
  12.         while(n--){  
  13.             scanf("%d%d",&x,&y);  
  14.             if(x>y)  
  15.                 swap(x,y);  
  16.             for(int i=(x+1)/2;i<=(y+1)/2;i++)  
  17.                 a[i]++;  
  18.         }  
  19.         int ans=0;  
  20.         for(int i=1;i<=200;i++)  
  21.             ans=max(ans,a[i]);  
  22.         printf("%d\n",ans*10);  
  23.     }  
  24.     return 0;  
  25. }  


1003

贪心思想,先放6*6,格子已经全部放满,然后放5*5,剩下的空间可以用来放1*1,然后放4*4,剩余的空间可以放2*2,然后放1*1,之后放3*3,同理处理完剩余空间,最后考虑2*2,1*1。

[cpp]  view plain copy
  1. #include<iostream>  
  2. #include<cstring>  
  3. #include<cstdio>  
  4. using namespace std;  
  5. int a,b,c,d,e,f;  
  6. int main(){  
  7.     int u[4]={0,5,3,1};  
  8.     while(scanf("%d%d%d%d%d%d",&a,&b,&c,&d,&e,&f)&&a+b+c+d+e+f){  
  9.         int ans=d+e+f+(c+3)/4;  
  10.         int x=d*5+u[c%4];  
  11.         if(b>=x)  
  12.             ans+=(b-x+8)/9;  
  13.         int y=36*ans-36*f-25*e-16*d-9*c-4*b;  
  14.         if(a>y)  
  15.             ans+=(a-y+35)/36;  
  16.         printf("%d\n",ans);  
  17.     }  
  18.     return 0;  
  19. }  


1004

不错的题目,暴力可解,但是没有意思。可以发现规律
排序之后,对于每一组相邻的差a[pos]-a[pos-1],当i取0-(pos-1)以及j取pos-n时,i和j之间的差值必然包括a[pos]-a[pos-1]。

那么a[pos]-a[pos-1]出现的次数是i*(n-i)

[cpp]  view plain copy
  1. #include<iostream>  
  2. #include<cstdio>  
  3. #include<cstring>  
  4. #include<algorithm>  
  5. using namespace std;  
  6. int a[10000],n;  
  7. int main(){  
  8.     while(scanf("%d",&n)!=EOF){  
  9.         for(int i=0;i<n;i++)  
  10.             scanf("%d",&a[i]);  
  11.         sort(a,a+n);  
  12.         LL ans=0;  
  13.         for(int i=1;i<n;i++)  
  14.             ans+=(LL)(a[i]-a[i-1])*i*(n-i);  
  15.         printf("%I64d\n",ans*2);  
  16.     }  
  17.     return 0;  
  18.   
  19. }  


1005

按两个关键字从小到大排序,之后遍历。

[cpp]  view plain copy
  1. #include<iostream>  
  2. #include<iomanip>  
  3. #include<cstdio>  
  4. #include<cstring>  
  5. #include<algorithm>  
  6. using namespace std;  
  7. struct Node{  
  8.     int l,r;  
  9. }a[5000];  
  10. int n;  
  11. bool cmp(Node n1,Node n2){  
  12.     return n1.l!=n2.l?n1.l<n2.l:n1.r<n2.r;  
  13. }  
  14. int main(){  
  15.     int t;  
  16.     scanf("%d",&t);  
  17.     while(t--){  
  18.         scanf("%d",&n);  
  19.         for(int i=0;i<n;i++)  
  20.             scanf("%d%d",&a[i].l,&a[i].r);  
  21.         sort(a,a+n,cmp);  
  22.         bool flag[5000];  
  23.         memset(flag,false,sizeof(flag));  
  24.         int ans=0;  
  25.         for(int i=0;i<n;i++){  
  26.             if(flag[i])  
  27.                 continue;  
  28.             int L=a[i].l,R=a[i].r;  
  29.             ans++;  
  30.             for(int j=i;j<n;j++)  
  31.                 if(a[j].l>=L&&a[j].r>=R&&flag[j]==false){  
  32.                     L=a[j].l;  
  33.                     R=a[j].r;  
  34.                     flag[j]=true;  
  35.                 }  
  36.         }  
  37.         printf("%d\n",ans);  
  38.     }  
  39.     return 0;  
  40. }  


1006

每个人手中有m张牌,有n个人,牌上的数字分别为1-n*m,互不相等。

赢的最少情况肯定是自己出大的,别人有大的,肯定压,否则别人出最小的。

每次选取最大的牌出,如果别人有大牌,则输,否则别人出最小的。不需要模拟,从大到小遍历一次。如果某张牌我有,说明我可以赢,+1,如果没有,说明别人可以比我大一次,-1。

[cpp]  view plain copy
  1. #include<iostream>  
  2. #include<iomanip>  
  3. #include<cstdio>  
  4. #include<cstring>  
  5. #include<algorithm>  
  6. using namespace std;  
  7. int a[1005],n,m,k,cas=0;  
  8. bool flag[1005];  
  9. int main(){  
  10.     while(scanf("%d%d",&n,&m)!=EOF&&n+m){  
  11.         memset(flag,false,sizeof(flag));  
  12.         for(int i=0;i<m;i++){  
  13.             scanf("%d",&k);  
  14.             flag[k]=true;  
  15.         }  
  16.         int ans=0,tmp=0;  
  17.         for(int i=n*m;i>0;i--)  
  18.             if(flag[i]){  
  19.                 tmp++;  
  20.                 ans=max(ans,tmp);  
  21.             }  
  22.             else  
  23.                 tmp--;  
  24.         printf("Case %d: %d\n",++cas,ans);  
  25.     }  
  26.     return 0;  
  27. }  


1007

离散化所有带宽。

枚举带宽,作为最小的带宽。然后在每一组选取满足最小带宽,而且价格最低的。

所以对于每一组按价格递增排序。优先考虑价格低的。

[cpp]  view plain copy
  1. #include<iostream>  
  2. #include<iomanip>  
  3. #include<cstdio>  
  4. #include<cstring>  
  5. #include<algorithm>  
  6. using namespace std;  
  7. struct Node{  
  8.     int b,p;  
  9. }a[400][400];  
  10. int t,m[400],B[160000],cnt,n;  
  11. bool cmp(Node n1,Node n2){  
  12.     return n1.p<n2.p;  
  13. }  
  14. int main(){  
  15.     scanf("%d",&t);  
  16.     while(t--){  
  17.         scanf("%d",&n);  
  18.         cnt=0;  
  19.         for(int i=0;i<n;i++){  
  20.             scanf("%d",&m[i]);  
  21.             for(int j=0;j<m[i];j++){  
  22.                 scanf("%d%d",&a[i][j].b,&a[i][j].p);  
  23.                 B[cnt++]=a[i][j].b;  
  24.             }  
  25.             sort(a[i],a[i]+m[i],cmp);  
  26.         }  
  27.         sort(B,B+cnt);  
  28.         int CNT=1;  
  29.         for(int i=1;i<cnt;i++)  
  30.             if(B[i]!=B[CNT-1])  
  31.                 B[CNT++]=B[i];  
  32.         double ans=0;  
  33.         for(int k=0;k<CNT;k++){  
  34.             int ptmp=0,flag=1;  
  35.             for(int i=0;i<n;i++){  
  36.                 int j;  
  37.                 for(j=0;j<m[i];j++)  
  38.                     if(a[i][j].b>=B[k])  
  39.                         break;  
  40.                 if(j==m[i]){  
  41.                     flag=0;  
  42.                     break;  
  43.                 }  
  44.                 ptmp+=a[i][j].p;  
  45.             }  
  46.             if(flag)  
  47.                 ans=max(ans,B[k]*1.0/ptmp);  
  48.         }  
  49.         printf("%.3f\n",ans);  
  50.     }  
  51.     return 0;  
  52. }  


1008

骑车去上学。时间为负的车子不用考虑,因为要不是追不上,要么追上也不是最快的。然后求出每辆车的所需时间,求出最小值。

[cpp]  view plain copy
  1. #include<iostream>  
  2. #include<iomanip>  
  3. #include<cstdio>  
  4. #include<cstring>  
  5. #include<algorithm>  
  6. using namespace std;  
  7. struct Node {  
  8.     int v,t,need;  
  9. }a[10000];  
  10. int n;  
  11. int main(){  
  12.     while(scanf("%d",&n)!=EOF&&n){  
  13.         for(int i=0;i<n;i++)  
  14.             scanf("%d%d",&a[i].v,&a[i].t);  
  15.         for(int i=0;i<n;i++){  
  16.             if(a[i].t<0)  
  17.                 a[i].need=inf;  
  18.             else{  
  19.                 a[i].need=(int)((4500*3.6)/a[i].v+a[i].t);  
  20.                 if((int)(4500*3.6)%a[i].v)  
  21.                     a[i].need++;  
  22.             }  
  23.         }  
  24.         int ans=a[0].need;  
  25.         for(int i=1;i<n;i++)  
  26.             ans=min(ans,a[i].need);  
  27.         printf("%d\n",ans);  
  28.     }  
  29.     return 0;  
  30. }  


1009

同样的根据价值递减排序,先满足价值高的先做,日期尽可能靠后。

[cpp]  view plain copy
  1. #include<iostream>  
  2. #include<iomanip>  
  3. #include<cstdio>  
  4. #include<cstring>  
  5. #include<algorithm>  
  6. using namespace std;  
  7. struct Node{  
  8.     int d,p;  
  9. }a[1000];  
  10. bool cmp(Node n1,Node n2){  
  11.     return n1.p>n2.p;  
  12. }  
  13. int n,t;  
  14. int main(){  
  15.     scanf("%d",&t);  
  16.     while(t--){  
  17.         scanf("%d",&n);  
  18.         for(int i=0;i<n;i++)  
  19.             scanf("%d",&a[i].d);  
  20.         for(int i=0;i<n;i++)  
  21.             scanf("%d",&a[i].p);  
  22.         sort(a,a+n,cmp);  
  23.         int ans=0;  
  24.         bool flag[10000];  
  25.         memset(flag,false,sizeof(flag));  
  26.         for(int i=0;i<n;i++){  
  27.             int j;  
  28.             for(j=a[i].d;j>=1;j--)  
  29.                 if(flag[j]==false){  
  30.                     flag[j]=true;  
  31.                     break;  
  32.                 }  
  33.             if(j==0)  
  34.                 ans+=a[i].p;  
  35.         }  
  36.         printf("%d\n",ans);  
  37.     }  
  38.     return 0;  
  39. }  


1010

按结束时间排序,然后依次遍历。

[cpp]  view plain copy
  1. #include<iostream>  
  2. #include<iomanip>  
  3. #include<cstdio>  
  4. #include<cstring>  
  5. #include<algorithm>  
  6. using namespace std;  
  7. struct Node{  
  8.     int l,r;  
  9. }a[100];  
  10. int n;  
  11. bool cmp(Node n1,Node n2){  
  12.     return n1.r!=n2.r?n1.r<n2.r:n1.l>n2.l;  
  13. }  
  14. int main(){  
  15.     while(scanf("%d",&n)!=EOF&&n){  
  16.         for(int i=0;i<n;i++)  
  17.             scanf("%d%d",&a[i].l,&a[i].r);  
  18.         sort(a,a+n,cmp);  
  19.         int ans=1,k=0;  
  20.         for(int i=1;i<n;i++)  
  21.             if(a[i].l>=a[k].r){  
  22.                 ans++;  
  23.                 k=i;  
  24.             }  
  25.         printf("%d\n",ans);  
  26.     }  
  27.     return 0;  
  28. }  


1011

贪心,每次优先选取价值高的,而且尽量时间靠后的。用flag数组标记,某天是否已经被利用,如果已经被利用,则往前遍历。

[cpp]  view plain copy
  1. #include<iostream>  
  2. #include<cstdio>  
  3. #include<cstring>  
  4. #include<algorithm>  
  5. using namespace std;  
  6. struct Node{  
  7.     int p,d;  
  8. }a[10000];  
  9. bool cmp(Node n1,Node n2){  
  10.     return n1.p>n2.p;  
  11. }  
  12. int n;  
  13. int main(){  
  14.     while(scanf("%d",&n)!=EOF){  
  15.         for(int i=0;i<n;i++)  
  16.             scanf("%d%d",&a[i].p,&a[i].d);  
  17.         sort(a,a+n,cmp);  
  18.         int ans=0;  
  19.         bool flag[10005];  
  20.         memset(flag,false,sizeof(flag));  
  21.         for(int i=0;i<n;i++)  
  22.             for(int t=a[i].d;t>0;t--)  
  23.                 if(flag[t]==false){  
  24.                     ans+=a[i].p;  
  25.                     flag[t]=true;  
  26.                     break;  
  27.                 }         
  28.         printf("%d\n",ans);  
  29.     }  
  30.     return 0;  
  31. }  


1012

对于每一个岛,存在一个区间,区间内任意位置建的雷达都能覆盖岛屿。这样就形成若干个区间。对于每一个区间从左到右遍历,尽可能选取最右端点,这样就能满足最多的区间。可以处理掉子区间。或者在遍历的时候遇到子区间,就尽可能取子区间的右端点。

[cpp]  view plain copy
  1. #include<iostream>  
  2. #include<iomanip>  
  3. #include<cstdio>  
  4. #include<cstring>  
  5. #include<algorithm>  
  6. using namespace std;  
  7. struct Node{  
  8.     double l,r;  
  9. }a[1000];  
  10. int n,d;  
  11. bool cmp(Node n1,Node n2){  
  12.     return n1.l<n2.l;  
  13. }  
  14. int main(){  
  15.     int cas=0;  
  16.     while(scanf("%d%d",&n,&d)!=EOF&&n+d){  
  17.         bool flag=true;  
  18.         for(int i=0;i<n;i++){  
  19.             int x,y;  
  20.             scanf("%d%d",&x,&y);  
  21.             if(abs(y)>d)  
  22.                 flag=false;  
  23.             if(!flag)  
  24.                 continue;  
  25.             a[i].l=x-sqrt((double)d*d-y*y);  
  26.             a[i].r=x+sqrt((double)d*d-y*y);  
  27.         }  
  28.         if(!flag){  
  29.             printf("Case %d: -1\n",++cas);  
  30.             continue;  
  31.         }  
  32.         sort(a,a+n,cmp);  
  33.         int ans=1;  
  34.         double pos=a[0].r;  
  35.         for(int i=1;i<n;i++)  
  36.             if(a[i].l>pos){  
  37.                 pos=a[i].r;  
  38.                 ans++;  
  39.             }  
  40.             else if(a[i].r<pos)  
  41.                 pos=a[i].r;  
  42.         printf("Case %d: %d\n",++cas,ans);  
  43.     }  
  44.     return 0;  
  45. }  

 

1013

对于每一个池塘,从左到右依次放木板。

[cpp]  view plain copy
  1. #include<iostream>  
  2. #include<iomanip>  
  3. #include<cstdio>  
  4. #include<cstring>  
  5. #include<algorithm>  
  6. using namespace std;  
  7. int n,d;  
  8. struct Node{  
  9.     int l,r;  
  10. }a[10000];  
  11. bool cmp(Node n1,Node n2){  
  12.     return n1.l<n2.l;  
  13. }  
  14. int main(){  
  15.     while(scanf("%d%d",&n,&d)!=EOF){  
  16.         for(int i=0;i<n;i++)  
  17.             scanf("%d%d",&a[i].l,&a[i].r);  
  18.         sort(a,a+n,cmp);  
  19.         int ans=0,pos=-inf;  
  20.         for(int i=0;i<n;i++){  
  21.             if(a[i].l>pos){  
  22.                 ans+=(a[i].r-a[i].l+d-1)/d;  
  23.                 pos=(a[i].r-a[i].l+d-1)/d*d+a[i].l;  
  24.             }  
  25.             else if(a[i].r>pos){  
  26.                 ans+=(a[i].r-pos+d-1)/d;  
  27.                 pos=(a[i].r-pos+d-1)/d*d+pos;  
  28.             }  
  29.         }  
  30.         printf("%d\n",ans);  
  31.     }  
  32.     return 0;  
  33. }  


1014

黑书上的例题。首先枚举走过的湖泊数X,则从1走到X,路上花的时间可以算出。每一次选一个鱼最多的湖泊钓鱼,对于每个湖泊来说,由于 在任何时候鱼的数目只和在这个湖泊里钓鱼的次数有关,和总次数无关。所以这样是最优的。

[cpp]  view plain copy
  1. #include<iostream>   
  2. #include<cstdio>   
  3. #include<cstring>   
  4. using namespace std;   
  5. int main()   
  6. {   
  7.     int n,h,f[30],d[30],t[30],Case=0;   
  8.     while(scanf("%d",&n),n>0)   
  9.     {   
  10.         if(Case!=0)  printf("\n");   
  11.         Case++;   
  12.         scanf("%d",&h);   
  13.         h=h*60;   
  14.         for(int i=1;i<=n;i++)   
  15.             scanf("%d",&f[i]);   
  16.         for(int i=1;i<=n;i++)   
  17.             scanf("%d",&d[i]);   
  18.         t[1]=0;   
  19.         for(int i=1;i<=n-1;i++)   
  20.         {   
  21.             int a;   
  22.             scanf("%d",&a);   
  23.             t[i+1]=t[i]+a*5;   
  24.         }   
  25.         int fish=0;   
  26.         int f_temp[30];   
  27.         int spe[30];   
  28.         int spe_temp[30];   
  29.         int tt;   
  30.         for(int i=1;i<=n;i++)   
  31.             spe[i]=-1;   
  32.         
  33.         for(int i=1;i<=n;i++)   
  34.         {   
  35.             int sum=0;   
  36.             tt=h-t[i];   
  37.             for(int j=1;j<=n;j++)   
  38.                 f_temp[j]=f[j];   
  39.             memset(spe_temp,0,sizeof(spe_temp));   
  40.             while(tt>=5)   
  41.             {   
  42.                 int mmax=0,maxj=-1;   
  43.                 for(int j=1;j<=i;j++)   
  44.                 {   
  45.                     if(f_temp[j]>mmax)   
  46.                     {   
  47.                         mmax=f_temp[j];   
  48.                         maxj=j;   
  49.                     }   
  50.                 }   
  51.                 if(maxj==-1)   
  52.                     break;   
  53.                     tt=tt-5;   
  54.                 spe_temp[maxj]++;   
  55.                 sum+=f_temp[maxj];   
  56.                 f_temp[maxj]=f_temp[maxj]-d[maxj];   
  57.             }   
  58.             if(sum>fish)   
  59.             {   
  60.                 fish=sum;   
  61.                 for(int j=1;j<=n;j++)   
  62.                     spe[j]=spe_temp[j];   
  63.                 spe[1]+=tt/5;   
  64.             }   
  65.             else if(sum==fish)   
  66.             {   
  67.                 bool flag=false;   
  68.                 for(int j=1;j<=n;j++)   
  69.                     if(spe[j]<spe_temp[j])   
  70.                     {   
  71.                         flag=true;   
  72.                         break;   
  73.                     }   
  74.                     else if(spe[j]>spe_temp[j])   
  75.                         break;   
  76.                 if(flag)   
  77.                 {   
  78.                     fish=sum;   
  79.                     for(int j=1;j<=n;j++)   
  80.                         spe[j]=spe_temp[j];   
  81.                     spe[1]+=tt/5;   
  82.                 }   
  83.             }   
  84.         }   
  85.         for(int i=1;i<n;i++)   
  86.             printf("%d, ",spe[i]*5);   
  87.         printf("%d\nNumber of fish expected: %d\n",spe[n]*5,fish);   
  88.     }   
  89.     return 0;   
  90. }  


1015

经典贪心,详见http://blog.csdn.net/acm_cxlove/article/details/7720218

 

1016

肯定所有的物品都要买,依次选取价值高的物品,这样打折的物品价格也高

[cpp]  view plain copy
  1. #include<iostream>  
  2. #include<iomanip>  
  3. #include<cstdio>  
  4. #include<cstring>  
  5. #include<algorithm>  
  6. using namespace std;  
  7. int t,n,a[20000];  
  8. int main(){  
  9.     scanf("%d",&t);  
  10.     while(t--){  
  11.         scanf("%d",&n);  
  12.         for(int i=0;i<n;i++)  
  13.             scanf("%d",&a[i]);  
  14.         sort(a,a+n);  
  15.         int ans=0;  
  16.         for(int i=n-3;i>=0;i-=3)  
  17.             ans+=a[i];  
  18.         printf("%d\n",ans);  
  19.     }  
  20.     return 0;  
  21. }  

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值