贪心算法 删数问题

目录

 

题目描述

输入格式

输出格式

输入输出样例

分析:


题目描述

键盘输入一个高精度的正整数NN(不超过250250位) ,去掉其中任意kk个数字后剩下的数字按原左右次序将组成一个新的正整数。编程对给定的NN和kk,寻找一种方案使得剩下的数字组成的新数最小。

输入格式

nn (高精度的正整数)

kk(需要删除的数字个数)

输出格式

最后剩下的最小数。

输入输出样例

输入 #1复制

175438 
4

输出 #1复制

13

 



分析:

- 首先:要让剩余的数最小,由于删的个数是确定的,即剩余的个数是确定的。当高位数字越小时,得到剩余的数字就越小。如此便得到此题的关键。

- 若要从长度为len的数中,删掉m个数字。首先如何确定要保留的最高位数字?

如果从34125中删掉2个数,显然最高位是1

如果从31245中删掉2个数,显然最高位仍然是1

如果从34215中删掉2个数,最高位最小只能是2

 

由此得到结论:第一位数字要从前m+1个数中选择一个最小的,前面的删掉。

 

- 同样的,第二位数字的选择和第一位是一样的道理。如果此时m已经用完,直接把后面的数拼接到结果数组中即可。否则仍按照上述规则寻找。

 

- 如果仅想到上面这些,并不能AC。原因是0的存在。。。。。。。

举个栗子:

从50074897中删除2个。答案是4897.

如果仍然按上述规则写,答案却是004897,此时,只需要考虑保存答案数组时,特判一下是否是0即可。

 

- 最后,把上面的全做完了,但。。。。。仍然不能AC。。。。。。。TMD!!!

再举个梨子,从10000中删除两个数。答案是0。按照上述规则来写,最后没有输出,因此,特判一下结果数组的长度,如果最后结果数组的长度是0,直接输出0.

 

代码如下:

#include <bits/stdc++.h>
using namespace std;

const int MAX = 255;
char str[MAX],res[MAX];
int N;

int main() {
    gets(str);
    scanf("%d",&N);
    int x = 0;
    while (str[x]=='0') x++;        //清空一下给出数字的前导0
    if(x) strcpy(str,str+x);
    int countRes=0,cut=0;
    for(int i=0; i+N+1 < strlen(str); i++) {
        if(N==0) {
            strcpy(res+countRes,str+i);    //已经删完,把后面的数拼接过来即可
            break;
        }
        int bk=i;
        for (int j = 0; j < N; ++j) {
            if(str[i+1+j]<str[bk]) {
                bk=j+1+i;
            }
        }
        N-=bk-i;                        //此次需要删除多少个,刷新一下N
        if(str[bk]!='0'){
            res[countRes++]=str[bk];      //特判,如果不是0才能添加到结果数组中
        }
        i=bk;                            //恢复i的索引。
    }
    if(countRes) puts(res);
    else puts("0");
}

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值