《算法竞赛·快冲300题》每日一题:“村庄与部落”

算法竞赛·快冲300题》将于2024年出版,是《算法竞赛》的辅助练习册。
所有题目放在自建的OJ New Online Judge。
用C/C++、Java、Python三种语言给出代码,以中低档题为主,适合入门、进阶。

每日一题汇总:http://oj.ecustacm.cn/viewnews.php?id=1023

文章目录

  • 题目描述
  • 题解
  • C++代码
  • Java代码
  • Python代码

村庄与部落” ,链接: http://oj.ecustacm.cn/problem.php?id=1823

题目描述

【题目描述】 n个村庄坐落成一条直线,A和B两个部落生活在这里。
  每个村庄要么无人居住,要么被两个部落之一所占据。
  如果一个无人居住的村庄两侧都是被部落A占据的村庄,那么这个村庄也视作被部落A占据;部落B亦同。
  请求出被部落A和B分别占据的村庄个数。
【输入格式】 第一行为正整数T,表示存在T组测试数据,1≤T≤20。
  每组测试数据输入一行,包含一个字符串s,表示每个村庄的状态,|s|≤100000
  字符串仅包含A、B、. 三种字符,分别表示被部落A占据、被部落B占据,以及无人居住。
【输出格式】 每组测试数据输出两个整数,分别表示被部落A和B控制的村庄数量。
【输入样例】

4
A..A..B...B
..A..
A....A
..B..B..B..

【输出样例】

4 5
1 0
6 0
0 7

题解

   这是典型的尺取法题目,用“快慢指针”对字符串做同向扫描,扫描过程中计算答案。设定两个指针i和j,其中快指针i在前,慢指针j在后。代码的步骤和逻辑是:
  (1)i每次往前扫描一个新字符,直到遇到字符A或B;j在后,停留在后面的一个A或B上。
  (2)若i、j指针指向的字符相同,例如都是A,那么统计A增加的村庄。
  (3)若i、j指针指向的字符不同,例如i指向A,j指向B,那么A的村庄加1。
  (4)在(2)、(3)之后,让j的新值等于i,开始下一轮的扫描。
【重点】 尺取法。

C++代码

#include
using namespace std;
int main(){
    int T;   cin >> T;
    while(T--){
        string s;  cin >> s;
        int ansA = 0, ansB = 0;
        int j = -1;                           //j是慢指针,初始值-1
        for(int i = 0; i < s.size(); i++) {   //i是快指针,从第一个字符s[0]开始扫描
            if(s[i] != '.') {                 //i停在A或B上
                if(j != -1 && s[j] == s[i])  { 
                    if(s[i] == 'A') ansA += i - j;
                    else            ansB += i - j;
                }
                else if(s[i] == 'A')  ansA++;
                else ansB++;
                j = i;                        //这一轮计算结束,开始下一轮
            }
        }
        cout<<ansA<<" "<<ansB<<endl;
    }
    return 0;
}

Java代码

import java.util.Scanner;
public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int T = sc.nextInt();
        while (T-- > 0) {
            String s = sc.next();
            int ansA = 0, ansB = 0;
            int j = -1;
            for (int i = 0; i < s.length(); i++) {
                if (s.charAt(i) != '.') {
                    if (j != -1 && s.charAt(j) == s.charAt(i)) {
                        if (s.charAt(i) == 'A')   ansA += i - j;
                        else                      ansB += i - j;                       
                    } 
                    else if (s.charAt(i) == 'A')  ansA++;
                    else                          ansB++;                   
                    j = i;                        
                }
            }
            System.out.println(ansA + " " + ansB);
        }
        sc.close();
    }
}

Python代码

T = int(input())
for _ in range(T):
    s = input()
    ansA, ansB = 0, 0
    j = -1                                       #j是慢指针,初始值-1
    for i in range(len(s)):                      #i是快指针,从第一个字符s[0]开始扫描
        if s[i] != '.':                          #i停在A或B上
            if j != -1 and s[j] == s[i]:
                if s[i] == 'A':  ansA += i - j
                else:            ansB += i - j
            elif s[i] == 'A':    ansA += 1
            else:                ansB += 1
            j = i                                #这一轮计算结束,开始下一轮
    print(ansA, ansB)

你可能感兴趣的:(算法竞赛快冲300题,尺取法)