🚀前言 🚀
大家好啊,这里是幸麟
🧩 一名普通的大学牲,最近在学习算法
🧩每日一题的话难度的话是根据博主水平来找的
🧩所以可能难度比较低,以后会慢慢提高难度的
🧩此题标签: *1500 贪心
🧩本文栏目:一起来打cf吧
期待各位的点赞+收藏+关注,订阅专栏,每天一起写一道cf吧
一起学习算法吧
题目
题目:
样例:
题目大意:
给你一个数x,你可以对这个数的任意一位进行删除,可以删除k次,希望你找到经过k次删除后最小的正数x
输入:
一个t代表测试组数
接下来有t组输入,每组包括两行,第一行为x,第二行为可以进行的删除操作k
输出:
输出t行,每一行为对应组别的最小正数x
输出:
比如7808652,你可以进行4次删除,删除后最小的正数x为7052
往下面翻就是答案了(想继续思考的话,还是不要往下面翻了)
答案+思路
因为x的位数比较大,所以这里我们用字符串s来存储x的每一位
用ans来表示经过k次删除后的x
我们已知k,所以经过k次删除后,ans的位数为s.size()-k
要让ans尽量小,我们可以选择尽量小的数字组成ans前面几位
比如在选择ans第一位的时候,我们可以先尝试能不能让1成为ans的首位,如果不能就尝试2,以此类推,在选择ans后面的位数时,则先尝试能不能让0成为首位,如果不能再一次试试1~9
如果可以找到这个数字,那我们就对x进行删除操作,直到删到选择数字的最小下标即可
具体可以再看看注释
#include <iostream>
#include <queue>
#include <map>
#include <unordered_map>
#include <vector>
#include <algorithm>
#include <cmath>
#include <string>
#include <cstring>
#include <set>
using namespace std;
typedef long long ll;
string s;
int main()
{
int t;
cin >> t;
while (t--)
{
int k;
int idx[10] = { 0 };
vector<int>a[10];
string ans;
cin >> s >> k;
for (int i = 0; i < s.size(); i++)
{
a[s[i] - '0'].push_back(i);//存每位数的下标
}
int l = 0;//l为删除的起点
int flag = 0;
while (k)
{
for (int i = 0; i <= 9; i++)
{
if (a[i].size() > idx[i] && (l > 0 || i != 0))
{
if (a[i][idx[i]] <= l + k)
{
k = k - (a[i][idx[i]] - l);
l = a[i][idx[i]] + 1;
idx[i]++;
ans += char(i + '0');
for (int x = 0; x <= 9; x++)//更新最小下标
{
if (a[x].size() > idx[x])
{
while (a[x][idx[x]]<l)
{
idx[x]++;
if (a[x].size() == idx[x])
{
break;
}
}
}
}
break;
}
}
}
if (k + l >= s.size())//删除的起点+还可以删除的次数大于了x的位数就可以不用删除了
{
flag = 1;
break;
}
}
if (flag)//ans就是答案
{
cout << ans << endl;
}
else//ans是答案的前几位
{
cout << ans;
for (int i = l; i < s.size(); i++)
{
cout << s[i];
}
cout << endl;
}
}
return 0;
}
好了,今天的每日一道到此结束了,
我发现了,好像1400~1600这个区间的,大部分题目都是贪心
马上就要期末考了,但是课上的记忆在离我远去
复习去了