P1106 删数问题
P1106删数问题
对2018年的我一次完美的对位单杀
2018 44pts Code
#include<cstdio>
#include<iostream>
#include<algorithm>
using std::cin;
using std::cout;
using std::sort;
using std::pair;
using std::string;
string zsk_lu_ping;
struct zsksb
{
int place;
int w;
bool operator < (const zsksb & rhs)
const{
return w>rhs.w;
}
}zsk_chao_ti_jie[43534];
int d;
int vis[3434];
int main(void)
{
cin>>zsk_lu_ping;
cin>>d;
for(int i=0;i<zsk_lu_ping.length();i++)
{
zsk_chao_ti_jie[i].place=i;
zsk_chao_ti_jie[i].w=zsk_lu_ping[i]-'0';
}
sort(zsk_chao_ti_jie,zsk_chao_ti_jie+zsk_lu_ping.length());
for(int i=0;i<d;i++)
{
vis[zsk_chao_ti_jie[i].place]=1;
}
for(int i=0;i<zsk_lu_ping.length();i++)
{
if(!vis[i])
{
cout<<zsk_lu_ping[i];
}
}
}
先来看看为什么错,2018年的做法是无脑找前K大的数,然后删去,这是存在问题的。
比如13928 2。如果按照这个算法,我会删去9、8,剩余的数是\(132\)。而显然删去3、9,剩余的数是128是一个更好的解法。
2023 72pts Code
#include <iostream>
using namespace std;
string s;
int k, minn, minP, sum;
char ans[300];
int main() {
cin >> s >> k;
for (int i = 0; i < s.length(); i++) {
minn = 100;
for (int j = i; j <= i + k; j++) {
if (minn > s[j] - '0') {
minn = s[j] - '0';
minP = j;
}
}
k -= minP - i;
i = minP;
ans[sum++] = s[minP];
}
for (int i = 0; i < sum; i++) {
cout << ans[i];
}
return 0;
}
时隔五年,我重做这道题目,放下浮躁慢慢想。
我事先知道这是贪心,把题目转化为这样一个问题
从当前最高位开始,在右端k位中寻找最小值,将最小值转到最高位,并将最高位移至最小值所在位的下一位。k减去最小值移动的位数。
这是一个正确的贪心。但我没有处理ans中的前导零,处理完细节后拿下AC.
#include <iostream>
using namespace std;
string s;
int k, minn, minP, sum, isFirst;
char ans[300];
int main() {
cin >> s >> k;
for (int i = 0; i < s.length(); i++) {
minn = 100;
for (int j = i; j <= i + k; j++) {
if (minn > s[j] - '0') {
minn = s[j] - '0';
minP = j;
}
}
k -= minP - i;
i = minP;
ans[sum++] = s[minP];
}
for (int i = 0; i < sum; i++) {
if (ans[i] == '0' && !isFirst) {
continue;
}
isFirst = true;
cout << ans[i];
}
if (!isFirst) {
cout << 0;
}
return 0;
}