贪心

贪心 -- 局部最优解 -> 全局最优解

Introduction

博才这边的教练要求巩固基础算法,然而我怀疑我买的一本通是本假书上的例题的代码假的,而且例题更是没有输入输出格式,所以,不管怎样我是不会按上面来的一定会做题

然后我没有了这个条件,转而看向竞赛宝典,本着巩固提高的方针看了看贪心

Body

还是一道例题理解一下:

题面

现在有一个数字\(N\),要求去掉\(S\)个数字,使这个数字去掉\(S\)个数字后最小,求去掉后的数字最小是多少?

输入格式

一行,一个数字\(N\),去掉数字的个数\(S\),中间用空格隔开

输出格式

一行,一个数字,表示去掉\(S\)个数字后的数字

样例输入

314 1

样例输出

14

数据范围

\[0<=S<N<=1e10000\]

首先,因为我们知道贪心是一个局部最优解->全局最优解的算法,所以相当于我们可以把每个步骤求一遍最优解然后继续求解,所以这个时候我们就可以考虑贪心具体的步骤了

现在请读者自己思考思考,答案在下方


想出来了吗?考虑到有一些Markdown编辑器的不支持的缘故,不采用字体颜色为白注释的做法请谅解

答案:

简单的从高位向低位,然后如果递减,那么选择最前面的一个,也就是该区间最大一个数字,如果递增,则选择最后一个,也就是该区间最大的一个数字

Code:

#include<cstdio>
#include<cstring>
using namespace std;
#define maxn 10005
char n[maxn];
int len;
inline void Delete_num(int num)
{
    for(int i=num;i<len-1;i++) n[i]=n[i+1];
    len--;
}
int main()
{
    scanf("%s",n);
    int s;
    scanf("%d",&s);
    len=strlen(n);
    int now=0;
    int st=0;
    int ans=s;
    bool book=0;
    bool flag=0;
    while(ans)
    {
        for(int i=0;i<len;i++) 
        {
            if(i==0)
            {
                if(n[i]==48) {Delete_num(i);flag=1;break;}
                continue;
            }
            if(n[i]<n[i-1]||(n[i]==n[i-1]&&now==1))
            {
                if(!now) now=1;
                if(now==1) continue;
                if(now==2) {Delete_num(i-1);ans--;book=1;now=0;break;}
            } 
            if(n[i]>n[i-1]||(n[i]==n[i-1]&&now==2))
            {
                if(!now) now=2;
                if(now==1){ Delete_num(st);ans--;book=1;now=0;break;}
                if(now==2) continue;
            }
        }
        if(flag){flag=0;continue;}
        if(book){book=0;continue;}
        if(now==1){Delete_num(st);ans--;continue;}
        if(now==2){Delete_num(len-1);ans--;}
    }
    for(int i=0;i<len;i++) printf("%c",n[i]);
    return 0;
}

中间的删除代码其实就是用时间换空间,如果你想要更少的时间,事实上你可以选择用空间换时间,空间大小为10005即可,所以用空间换时间是一个不错的选择,但是由于作者比较懒惰,所以还请读者自主思考

接下来还是讲题:

题面

给定一个由正整数组成的数列,要求你用合并操作合成一个数字,h合并过程如下:
给定两个数字a,b;有合并之后的数字c=a*b+1;
给定一个数列,求它的极差,也就是最大值和最小值之差

输入格式

两行,第一行一个正整数n
第二行n个正整数表示一个序列

输出格式

一行,一个数字表示极差

数据范围和解释

\(1 \leqslant n \leqslant 100000\)
\(1 \leqslant a_i \leqslant 2147483647(Maxint)\)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章