P1106 删数问题_题解

P1106 删数问题

题目描述

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

输入格式

输入两行正整数。

第一行输入一个高精度的正整数n。

第二行输入一个正整数k,表示需要删除的数字个数。

输出格式

输出一个整数,最后剩下的最小数。

输入输出样例 #1

输入 #1

175438 
4

输出 #1

13

说明/提示

用len(n)表示n的位数,保证 1≤k<len(n)≤250。

注意:去掉若干数字后剩下的数可以存在前导零,而输出时不要输出前导零。

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

string N;
int K;
int q;//原数的位数
int p;//新数的位数 

string ans="";

void dfs(int position,int step)//每一层都有个回溯值 
{
    if(step>=p) return;
    int min_num=100;//最小值
    int min_position;//记录一下最小值位置,因为下次只能选后面的了 
    for(int i=position;i<q-(p-step/*p减去已经拿了的位数即是没有拿的*/)+1/*加1是因为此时还没有记录层数*/;i++)//防止后面没拿的了 
    {
        if(N[i]-'0'<min_num)//不能写等于,如果都一样要先拿前面,给后续选数留下空间 
        {
            min_num=N[i]-'0';
            min_position=i;
        }
    }
    char mn=min_num+'0';
    ans+=mn;
    dfs(min_position+1,step+1);
}

int main()
{
    cin>>N;
    cin>>K; 
    q=N.length();
    p=N.length()-K;//新数的位数
    dfs(0,0);
    
    int u=ans.length();
    int flag=true;//定义一个flag看0串结束没有 
    for(int i=0;i<u;i++)//本题巨坑点,前几位可以全是是0,自动忽略。之前我还专门特判不能为0…… 
    {
        if(ans[i]=='0'&&flag) continue;
        else
        {
            flag=false;
            cout<<ans[i];
        }
    }
    //特判只有一个0     
    if(u==1&&ans[0]=='0')
    {
        cout<<"0"<<endl;
    }
    cout<<endl;
    return 0;
} 
posted @ 2025-11-30 17:07  gdyyx  阅读(4)  评论(0)    收藏  举报