cf训练题(1)

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;
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值