SDUT 2019 级程序设计基础(B)II 实验5–贪心

6月5日下午刚上完高数课,老师没留作业,正好有空把贪心开了,这几天程设敲下来感觉也不是没有收获,很多上学期初学的也能理解较为透彻了,无论递推递归还是贪心动规,理解思想最重要,一味记例题没有意义,多敲题,多思考,最后还是祝所有人期末能AK~
总题目链接

5-1删数问题

一开始没考虑全面,认为每次直接贪掉所有数字里面最大的就行,但是如10230450删两个就变成了102300其实最小是删1和3变成200。

  • 原理如下:
    贪心就是要每次删数后都使这个数是所有情况里最小的,我们知道高位的数对数大小的影响大,其次是数字大小,删掉一个数后面的数会逐个顶上来,如果是递增的数字那么删掉最大的数就能使它最小,但如果是先增后减再增则删掉那个极值点(表达可能不严谨,理解意思就行),比如136519,虽然最大的是9,但应该删6。如此我们得到删数的方法——每次判断各位数字如果递增则删去最后一个,否则删去第一个递减的点(这里注意第一个递减的点前面可的数可能有相等的点,要在代码里体现)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
    char s[101];
    int n;
    while(~scanf("%s %d",s,&n))
    {
        int m=strlen(s);
        while(n--)
        {
            int i=0;
            while(s[i]<=s[i+1]&&i+1<m)//不能少了等于好
            {
                i++;
            }
            if(i!=m-1)
            for(int j=i;j<m;j++)
            {
                s[j]=s[j+1];
            }
                       m--;
//            for(int k=0;k<m;k++)
//                printf("%c",s[k]);
//            printf("\n");

        }
        int i=0;
        while(s[i]=='0'&&i<m) i++;
        if(i==m) printf("0\n");
        else
        {
            for(int j=i;j<m;j++)
            printf("%c",s[j]);
            printf("\n");
        }

    }
    return 0;
}

5-2活动选择

注意编号1-n ,每次在当前时间选结束最早的就行,按结束时间排序就行。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct node
{
    int begin,end,num;
} a[101],t;

int main()
{
    int n;
    scanf("%d",&n);
    for(int i=0; i<n; i++)
    {
        scanf("%d %d",&a[i].begin,&a[i].end);
        a[i].num=i+1;
    }
    for(int i=0; i<n-1; i++)
    {
        for(int j=0; j<n-i-1; j++)
        {
            if(a[j].end>a[j+1].end)
            {
                t=a[j];
                a[j]=a[j+1];
                a[j+1]=t;
            }
        }
    }
    int now=a[0].end;
    printf("%d",a[0].num);
    for(int i=1; i<n; i++)
    {
        if(a[i].begin>=now)
        {
            printf(",%d",a[i].num);
            now=a[i].end;
        }
    }
    return 0;
}

5-3活动选择问题

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct node
{
    int begin,end;
} a[101],t;

int main()
{
    int n;
    while(~scanf("%d",&n))
    {
        for(int i=0; i<n; i++)
        {
            scanf("%d %d",&a[i].begin,&a[i].end);
        }
        for(int i=0; i<n-1; i++)
        {
            for(int j=0; j<n-i-1; j++)
            {
                if(a[j].end>a[j+1].end)
                {
                    t=a[j];
                    a[j]=a[j+1];
                    a[j+1]=t;
                }
            }
        }
        int now=0;
        int ans=0;
        for(int i=0; i<n; i++)
        {
            if(a[i].begin>=now)
            {
                ans++;
                now=a[i].end;
            }
        }
        printf("%d\n",ans);
    }

    return 0;
}

5-4区间覆盖问题

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//冒泡模板flag判断升序降序
void sort(int *a,int n,int flag)
{
    int t;
    if(flag)
    {
        for(int i=0; i<n; i++)
        {
            for(int j=0; j<n-i-1; j++)
            {
                if(a[j]>a[j+1])
                {
                    t=a[j];
                    a[j]=a[j+1];
                    a[j+1]=t;
                }
            }
        }
    }
    else
    {
        for(int i=0; i<n; i++)
        {
            for(int j=0; j<n-i-1; j++)
            {
                if(a[j]<a[j+1])
                {
                    t=a[j];
                    a[j]=a[j+1];
                    a[j+1]=t;
                }
            }
        }
    }

}

int main()
{
    int n,m;
    int a[201],dis[201];
    while(~scanf("%d %d",&n,&m))
    {
        for(int i=0;i<n;i++)
            scanf("%d",&a[i]);
        if(n<=m)
            printf("%d\n",n);
        else
        {
            sort(a,n,1);
            for(int i=0;i<n-1;i++)
                dis[i]=a[i+1]-a[i]-1;
            sort(dis,n-1,0);
            int ans=a[n-1]-a[0]+1;
            for(int i=0;i<m-1;i++)
                ans-=dis[i];
            printf("%d\n",ans);
        }
    }

    return 0;
}

5-5最少拦截系统

用一个数组a记录每套系统的最大拦截高度,每次拦截导弹先从小到大遍历数组a,若能拦截则更新那个拦截系统的最大高度,否则再弄一个新的拦截系统

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main()
{
    int n;
    int a[201],x;
    while(~scanf("%d",&n))
    {
        memset(a,-1,sizeof(a));
        int m=0;
        while(n--)
        {
            scanf("%d",&x);
            int i;
            for(i=0;i<m;i++)
                if(x<=a[i])
            {
                a[i]=x;
                break;
            }
            if(i==m)
            {
                a[m++]=x;
            }
        }
        printf("%d\n",m);
    }

    return 0;
}

5-6悼念512汶川大地震遇难同胞

这题只要买过东西的都会做吧…

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct node
{
    int p,h;
}a[1001],t;

int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        int n,m;
        scanf("%d %d",&n,&m);
        for(int i=0;i<m;i++)
        {
            scanf("%d %d",&a[i].p,&a[i].h);
        }
        for(int i=0; i<m; i++)
        {
            for(int j=0; j<m-i-1; j++)
            {
                if(a[j].p>a[j+1].p)
                {
                    t=a[j];
                    a[j]=a[j+1];
                    a[j+1]=t;
                }
            }
        }
        double ans=0;
        int i;
        for(i=0;i<m;i++)
        {
            if(a[i].h*a[i].p>n)
            {
                break;
            }
            ans+=a[i].h*1.0;
            n-=a[i].h*a[i].p;
        }
        ans=ans+n*1.0/a[i].p;
        printf("%.2f\n",ans);
    }
    return 0;
}

5-7懒虫小鑫

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct node
{
    int p,h;
}a[10001],t;


void sort(int l,int r)//快排
{
    t=a[l];
    int i=l,j=r;
    if(l>=r) return;
    while(i<j)
    {
        while((a[j].h>t.h||(a[j].h==t.h&&a[j].p<=t.p))&&i<j) j--;
        a[i]=a[j];
        while((a[i].h<t.h||(a[i].h==t.h&&a[i].p>=t.p))&&i<j) i++;
        a[j]=a[i];
    }
    a[i]=t;
    sort(l,i-1);
    sort(i+1,r);
}


int main()
{
    int n,m;
    while(~scanf("%d %d",&n,&m))
    {
        for(int i=0;i<n;i++)
        {
            scanf("%d %d",&a[i].h,&a[i].p);
        }
        sort(0,n-1);
        int ans=0;
        for(int i=0;i<m;i++)
        ans+=a[i].p;
        printf("%d\n",ans);
    }
    return 0;
}

5-8装船问题

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct node
{
    int p,h,x;
} a[10001],t;


void sort(int l,int r)
{
    t=a[l];
    int i=l,j=r;
    if(l>=r)
        return;
    while(i<j)
    {
        while(a[j].x<=t.x&&i<j) j--;
        a[i]=a[j];
        while(a[i].x>=t.x&&i<j) i++;
        a[j]=a[i];
    }
    a[i]=t;
    sort(l,i-1);
    sort(i+1,r);
}


int main()
{
    int m;
    scanf("%d",&m);
    for(int i=0; i<10; i++)
    {
        scanf("%d %d",&a[i].p,&a[i].h);
        a[i].x=a[i].p/a[i].h;
    }
    sort(0,9);
    int ans=0;
    int i;
    for(i=0; i<10; i++)
    {
        if(a[i].h<=m)
        {
            ans+=a[i].p;
            m-=a[i].h;
        }
        else 
        {
           ans+=m*a[i].x; 
           break;
        }
    }    
    printf("%d\n",ans);
    return 0;
}

5-9商人小鑫

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int a[10000001],t;

void sort(int l,int r)
{
    t=a[l];
    int i=l,j=r;
    if(l>=r)
        return;
    while(i<j)
    {
        while(a[j]<=t&&i<j)
            j--;
        a[i]=a[j];
        while(a[i]>=t&&i<j)
            i++;
        a[j]=a[i];
    }
    a[i]=t;
    sort(l,i-1);
    sort(i+1,r);
}


int main()
{
    int m,n;
    while(~scanf("%d %d",&n,&m))
    {
        for(int i=0; i<n; i++)
        {
            int x,y;
            scanf("%d %d",&x,&y);
            a[i]=y-x;
        }
        sort(0,n-1);
        int ans=0;
        for(int i=0; i<m; i++)
        {
            ans+=a[i];
        }
        printf("%d\n",ans);
    }
    return 0;
}

5-10商人的诀窍

注意是要买更多的苹果,所以是比质量/价格

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct node
{
    int p,h;
    double x;
} a[10001],t;


void sort(int l,int r)
{
    t=a[l];
    int i=l,j=r;
    if(l>=r)
        return;
    while(i<j)
    {
        while(a[j].x<=t.x&&i<j)
            j--;
        a[i]=a[j];
        while(a[i].x>=t.x&&i<j)
            i++;
        a[j]=a[i];
    }
    a[i]=t;
    sort(l,i-1);
    sort(i+1,r);
}


int main()
{
    int m,n;
    while(~scanf("%d %d",&n,&m)&&m!=-1&&n!=-1)
    {
        for(int i=0; i<m; i++)
        {
            scanf("%d %d",&a[i].h,&a[i].p);
            a[i].x=a[i].h*1.0/a[i].p*1.0;
        }
        sort(0,m-1);
        double ans=0;
        int i;
        for(i=0; i<m; i++)
        {
            if(a[i].p<=n)
            {
                ans+=1.0*a[i].h;
                n-=a[i].p;
            }
            else
            {
                ans+=n*1.0*a[i].x;
                break;
            }
        }
        printf("%.3f\n",ans);
    }

    return 0;
}

小结

这次小鑫出场率真高,堪比数学界的小明,英语界的李华。
贪心问题用于求一个问题的最优解,如果能保证每次操作都是此次操作所有可能最优的一个,那么就能求出最优解,贪心原理好理解,但有些题还是需要一定思维,此章节顺带还会考排序,需要注意。

暂无评论

发送评论 编辑评论


|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇