Advertisement

上海计算机学会2023年12月月赛C++丙组T5特定的串

阅读量:

特定的串

内存限制: 256 Mb时间限制: 1000 ms

题目描述

给定一个 01 序列 b1​b2​…bn​,01 的意思就是这个数列里只有 01

我们可以修改该序列的任意一个数字,可以将 0 变成 1,也可以将 1 变成 0,注意不能删除或增加数字。

请问,最少需要修改多少数字才能让给定的序列中不含有特定的一个子串 110。

输入格式
  • 第一行:单个整数 n。
  • 第二行:n 个字符表示 b1​b2​…bn​,保证只出现 01
输出格式
  • 单个整数表示答案
数据范围
  • 对于 30% 的数据,1≤n≤20;
  • 对于 60% 的数据,1≤n≤2000;
  • 对于 100% 的数据,1≤n≤500,000
样例数据

输入:
4
1101
输出:
1
说明:
改0为1
输入:
5
11000
输出:
1
说明:
该第二个1为0

解析:

想要消灭110串,两种办法:

一是把所有0改成1;

二是把所有11改成10;

取最小值,可以得90分

详见代码:

复制代码
 #include<bits/stdc++.h>

    
 using namespace std;
    
 int n;
    
 int ans1=0;//把0都变成1
    
 int ans2=0;//把11变成10
    
 int main() {
    
     cin >> n;
    
     int num=0;//统计连续1的个数
    
     for (int i=1;i<=n;i++){
    
     char ch;
    
     cin>>ch;
    
     if (ch=='0'){
    
         ans1++;
    
         ans2+=num/2;
    
         num=0;
    
     }else{
    
         num++;
    
     }
    
     }
    
     cout<<min(ans1,ans2);
    
     return 0;
    
 }
    
    
    
    

正解:

以所有的01为分界线,可以把前边所有的11改成10,把后边所有的0改成1,取最小值。

详见代码:

复制代码
 #include<bits/stdc++.h>

    
 using namespace std;
    
 int n;
    
 int ans2=0;//把11变成10
    
 int a[500005];//a[i]表示从i位置开始到结尾一共多少个0
    
 string s;
    
 int ans=1e9;
    
 int main() {
    
     cin>>n;
    
     cin>>s;
    
     s+='0';
    
     for(int i=n-1;i>=0;i--){
    
     if (s[i]=='0'){
    
         a[i]=a[i+1]+1;
    
     }else{
    
         a[i]=a[i+1];
    
     }
    
     }
    
     int num=0;//统计连续1的个数
    
     for (int i=0;i<=n;i++){
    
     if (s[i]=='0'){
    
         ans=min(ans,ans2+a[i]);
    
         ans2+=num/2;
    
         num=0;
    
     }else{
    
         num++;
    
     }
    
     }
    
     cout<<ans;
    
     return 0;
    
 }
    
    
    
    

全部评论 (0)

还没有任何评论哟~