CF1506B Partial Replacement 题解
\(\text{Description}\)
给定长度为 \(n\) 的字符串 \(s\) 和 \(k\),字符串仅由 .
和 *
组成,初始将最靠前和最靠后的 *
变为 x
,然后你可以任意将 *
变为 x
,求最小的将 *
变为 x
的次数使得任意两个 x
之间的距离小于等于 \(k\)。
数据保证有解。
\(\text{Solution}\)
考虑贪心,对于每一个 x
,寻找离他最远的 *
且满足距离不大于 \(k\),将这个 *
变成 x
。
关于正确性:因为要使任意两个相邻的 x
之间距离都不超过 \(k\) ,所以选择尽可能远的能够使 x
之间的距离尽可能远,这样子就可以使 x
尽可能少。
\(\text{Code}\)
/*If you are full of hope,you will be invincible*/
#include <bits/stdc++.h>
#include<ext/pb_ds/assoc_container.hpp>
#include<ext/pb_ds/hash_policy.hpp>
#include<ext/pb_ds/priority_queue.hpp>
using ll = long long ;
using lb = long double;
using u32 = unsigned int;
using u64 = unsigned long long ;
using std::cin ;
using std::cout ;
std::mt19937 hpy(time(nullptr)+(unsigned long long)(new char));
int t,n,k,ans,cnt,a[100],vis[100];
char s[100];
inline void solve() {
memset(a,0,sizeof a),memset(vis,0,sizeof vis),cnt = 0,ans = 0;
for(int i = 1 ; i <= n;++i) {
if(s[i] == '*') a[++cnt] = i;
} if(cnt <= 2) return ans = cnt,void();//特判
ans = 2;
vis[a[1]] = vis[a[cnt]] = 1;
for(int i = 1;i <= cnt;++i) {
if(vis[a[i]] == 1) {
for(int j = std::min(a[i]+k,n);j > a[i];--j) {
if(s[j] == '*') {
if(vis[j]) break;
vis[j] = 1,++ans ;
break ;
}
}
}
}
}
int main() {
std::ios::sync_with_stdio(false);
scanf("%d",&t);
while(t--) scanf("%d%d %s",&n,&k,s+1),solve(),printf("%d\n",ans);
return 0;
}