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;
}

猜你喜欢

转载自blog.csdn.net/weixin_51443397/article/details/115257621