貪心

貪心 -- 局部最優解 -> 全局最優解

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)\)

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