题解:P1106 删数问题
题意简述
给定一个不超过 \(250\) 位的正整数 \(n\),要求删去其 \(k\) 个不同数位上的数字后,使得剩下的数字尽可能大。
思路
最直接的考虑:设 \(n\) 的位数为 \(len\),则剩下的数字一定是 \(len-k\) 位数。首先我要最小化他最高位上的数字。
这是第一步的操作。因此不难想到后面的操作将第一步确定的最高位跳过,对后面的数继续删除。
于是很自然地将 \(k\) 看作是一种“货币”,我删除数字需要消耗货币,然而对于每一次都尽可能最小化最高位,因为最高位更小的策略显然是更优的。那么对于相同大小的最高位,优先选择消耗货币较少的,即需要删除数字较少的。
于是我们就获得了此题的贪心策略。其实一道贪心题被看出是贪心了它就是水题了。
代码实现要注意前导零的处理。前导零的具体处理细节详见代码注释。
代码
#include<bits/stdc++.h>
#define ios ios::sync_with_stdio(0),cin.tie(0),cout.tie(0)
using namespace std;
string n;
int k;
bool flag=0; // 记录这个数是不是删得只剩一个 0 了
// 如果删得只剩一个 0 了就要输出 0
int main(){
ios;
cin>>n>>k;
int pos=0,len=n.size();
int T=len-k;
while(T--){ // 每次确定一位上的数字
int x=10,p=pos;
for(int i=pos;i<=pos+k;i++){
if((n[i]-'0')<x)x=n[i]-'0',p=i;
}
if(x)flag=1;
if(flag)cout<<x;
k-=p-pos; // 将 [pos,p] 中间全部删去
pos=p+1;
}
if(!flag)cout<<"0\n"; // 什么都没输出过说明这个数字就是 0
return 0;
}
感谢阅读!
本文来自博客园,作者:Circle_Table,转载请注明原文链接:https://www.cnblogs.com/Circle-Table/articles/19507048

浙公网安备 33010602011771号