AcWing:4967. 翻转

标签:思维题

描述

小蓝用黑白棋的 n 个棋子排成了一行,他在脑海里想象出了一个长度为 n 的 01 串 T,他发现如果把黑棋当做 1,白棋当做 0,这一行棋子也是一个长度为 n 的 01 串 S。

小蓝决定,如果在 S 中发现一个棋子和它两边的棋子都不一样,就可以将其翻转变成另一个颜色。

也就是说,如果 S 中存在子串 101 或者 010,就可以选择将其分别变为 111 和 000,这样的操作可以无限重复。

小蓝想知道最少翻转多少次可以把 S 变成和 T 一模一样。

输入格式

输入包含多组数据。

输入的第一行包含一个正整数 D 表示数据组数。

后面 2D 行每行包含一个 0101 串,每两行为一组数据,第 2i−1 行为第 i 组数据的 Ti,第 2i 行为第 i 组数据的 Si,Si 和 Ti长度均为 ni。

输出格式

对于每组数据,输出一行包含一个整数,表示答案,如果答案不存在请输出 −1

数据范围

对于 20% 的评测用例,1≤∑1Dni≤10;
对于所有评测用例,保证 1≤∑1Dni≤10^6,ni>0。

输入样例:
2
1000111
1010101
01000
11000
输出样例:
2
-1
 来源:第十四届蓝桥杯省赛C++C/研究生组 , 第十四届蓝桥杯省赛PythonA/C组

讲讲思路:

一开始我还以为还考虑多次翻转,但是后来一想,翻转只影响中间的数,翻转完中间的数,那中间的数已经和两边相等,那就不可能再转,所以我们只需要考虑需要翻转的数

以下是AC代码:

#include 
#include 
#include 

using namespace std;

string s1 , s2;

int main()
{
    int t;
    cin >> t;
    while(t --)
    {
        /* 初始化 */
        int cnt = 0;
        bool f = true;
        
        /* string直接读 */
        cin >> s1 >> s2;
        
        /* 核心循环 */
        for (int i = 0; i < s1.size(); i ++ )
        {
            /* 找不同 */
            if(s1[i] != s2[i])
            {
                
                if(i == 0 && i == s1.size() - 1) // 首末转不了,直接出循环 
                {
                    f = false;
                    break;
                }
                if(s2[i - 1] == s2[i + 1] && s1[i] == s2[i - 1]) // 判断两边是否相等,两边是否等于答案
                {
                    cnt ++; // 计数
                    s2[i] = s2[i - 1]; // 翻转
                }
                else
                {
                    f = false;
                    break;
                }
            }
            
        }
        
        /* 判断输出 */
        if(f) cout << cnt << endl;
        else cout << "-1" << endl;
        
    }
    return 0;
}

你可能感兴趣的:(算法)