B
题意:给你一个由.和*组成的字符串和数字k,要求第一个 * 和最后一个 * 换成x,中间的一些 * 换成x,但两个x之间的距离不能超过k,求最少替换数。
这个题不算太难,但是做的时候改了很多遍都没有通过,我一开始的思路是从前往后找到第一个 * 就加一,然后记录下这个位置,在这个位置基础上加k,判断那个位置是否为 * ,是就更新位置,不是就k- -,(必须提前把k赋值给另一个数)在这个位置上继续加k,直到发现 * 然后更新位置,重复以上过程。做题的时候也一直觉得这个方法没有错,改了很多遍终于过了,以下是代码调试过程。
错解:
#include<iostream>
#include<string>
using namespace std;
int main()
{
int t;
cin>>t;
while(t--)
{
int n,k,i,r=0,d=0,x;
string s;
cin>>n>>k>>s;
for(i=0; i<n; i++)
{
if(r==0&&s[i]=='*')
{
d++;
r=i;
}
x:
if(r+k<n&&s[r+k]=='*')
{
r=r+k;
d++;
i=i+k;
}
else {
k--;
if(k>0)
goto x;
}
}
cout<<d<<endl;
}
return 0;
}
错题原因:(1)没有将k的值保存,第一次判断时k就减没了。(2)没有考虑r+k>n的情况。(3)如果i=0时就为 * ,r=i,相当于没有把i=0视为第一个出现的 *
改后正解
#include<iostream>
#include<string>
using namespace std;
int main()
{
int t;
cin>>t;
while(t--)
{
int n,k,i,r=0,d=0,x,c;
string s;
cin>>n>>k>>s;
c=k;
for(i=0; i<n; i++)
{
k=c;
if(r==0&&s[i]=='*')
{
d++;
r=i;//cout<<"r="<<r<<endl;
}
if(d!=0)
{
x:
if(r+k<n&&s[r+k]=='*')
{
r=r+k;
d++;
i=r;//cout<<"i="<<i<<endl;
continue;
}
else {
if(r+k>=n)
break;
k--;
if(k>0)
goto x;
}
}
}
for(i=r+1; i<n; i++)
{
if(s[i]=='*')
{
d++;
break;
}
}
cout<<d<<endl;
}
return 0;
}
这种做法代码挺长的,太过复杂,学习了一下其他选手的代码,基本方法都是一样的,只不过先找了第一个 * 和最后一个 * 的位置,代码比较精简,学习一下
#include<iostream>
#include<string>
using namespace std;
int main()
{
int t;
cin >> t;
while(t--)
{
int n,k;
string s;
cin >> n >> k >> s;
int l=0,r=n-1,ans=1;
while(s[l]!='*') l++;
while(s[r]!='*') r--;
for(int i=l ; i<r ; i+=k)
{
while(s[i]=='.')i--;
ans++;
}
cout << ans << endl;
}
return 0;
}