删数游戏
输入一个高精度的正整数n(n≤240)去掉其中任意s(s≤n)个数字后剩下的数字按原顺序组成一个新的正整数。
编程对给定的n和s,寻找一种方案使得剩下的数字组成的新数最小,并输出最小数。
n
s
Output
最后剩下的最小数
175438
4
Sample Outple
13
Analysis
应为正整数n最多有240位,所以采用字符串储存n。
我们选择的贪心策略是:每一步删去/删去后能使剩下正整数最小/的数。从高位开始,若各位数字递增则删去最后一个数字,否则删除第一个递减区间的首字符,然后回到串首,以此重复s次,剩下的便是解了。
删数过程如下:
n=175438 //删7
15438 //删5
1438 //删4
138 //删8
13 //解为13
Code
#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
int main()
{
string n;
int s;
cin>>n>>s;
while(s--)
for(int i=0;i<n.length();i++)
if(n[i]>n[i+1]||i==n.length())
{
n.erase(i,1);
break;
}
while(n[0]=='0' &&n[1])n.erase(0,1);
cout<<n;
}
接下来看一看数据加强版
给出一个N位数字串,删除任意K位,使剩下的数最大。
第1行:2个整数N和K(1<=K<=N<=500000)
第2行:N个数字(可能为0)
Output
第1行:1个可行到的最大的数
10 4
4177252841
Sample Output
775841
Analysis
我们可以模拟一个栈
按顺序将字符串入栈;
每次入栈时,如果栈顶元素<入栈元素,就弹出栈顶元素,并且弹出次数递减,减到0为止;
然后不要急着入栈,要加一个while继续枚举下面的元素(有可能下面的元素依然小于入栈元素);
这里会有特判(在代码中解释)
Code
#include<cstdio>
int tail,zhan[500005],n,k,g;
int main()
{
scanf("%d%d\n",&n,&k);
g=k;
zhan[tail]=999999999;
for(int i=1;i<=n;i++)
{
char x;
scanf("%c",&x);
int y=x-'0';
bool f=0;
while(y>zhan[tail]&&k)
{
zhan[tail]=y;
tail--;
f=1;
k--;
}
tail++;
if(!f)zhan[tail]=y;
}
if(n==g){printf("0\n");return 0;}
if(k)
for(int i=1;i<=n-k;i++)
printf("%d",zhan[i]);
else
for(int i=1;i<=tail;i++)
printf("%d",zhan[i]);
}