题解:AtCoder AT_awc0046_c Seating Arrangement

【题目来源】

AtCoder:C - Seating Arrangement

【题目描述】

Takahashi is in charge of arranging \(N\) seats lined up in a row at a cultural festival venue. The seats are numbered \(1\) through \(N\) from left to right.
高桥负责安排文化节会场上一排 \(N\) 个座位的安排。座位从左到右编号为 \(1\)\(N\)

Currently, some seats are already occupied by guests. Specifically, seat \(i\) is occupied if \(S_i = 1\), and vacant if \(S_i = 0\).
目前,一些座位已经被客人占据。具体来说,如果 \(S_i = 1\),则座位 \(i\) 已被占据;如果 \(S_i = 0\),则座位 \(i\) 为空。

Takahashi can select \(0\) or more vacant seats as he likes and guide one new guest to each selected seat. However, he cannot move or remove guests who are already seated. Also, each seat can hold at most \(1\) person. Furthermore, due to the venue's ventilation rules, the following condition must be satisfied:
高桥可以任意选择 \(0\) 个或更多空座位,并引导一位新客人到每个选中的座位。但是,他不能移动或移除已经就坐的客人。同时,每个座位最多容纳 \(1\) 人。此外,由于会场的通风规定,必须满足以下条件:

  • After all guests have been guided to their seats, there must be no three consecutive seats that are all occupied.
    在所有客人被引导到座位后,不能存在三个连续的座位全部被占据

In other words, if we denote the state of seat \(i\) after all guidance is complete as \(T_i\) (\(1\) if occupied, \(0\) if vacant), then for every \(i\) satisfying \(1 \leq i \leq N-2\), it must not be the case that \(T_i = T_{i+1} = T_{i+2} = 1\). It is guaranteed in the input that the initial state already satisfies this condition.
换句话说,如果用 \(T_i\) 表示引导完成后座位 \(i\) 的状态(\(1\) 表示被占据,\(0\) 表示空),那么对于每个满足 \(1 \leq i \leq N-2\)\(i\),不能有 \(T_i = T_{i+1} = T_{i+2} = 1\)。输入保证初始状态已满足此条件。

Takahashi wants to guide as many new guests as possible while satisfying this condition. Find the maximum number of new guests that can be guided.
高桥希望在满足此条件的情况下,引导尽可能多的新客人。求可以引导的新客人的最大数量。

【输入】

\(N\)
\(S_1\) \(S_2\) \(\ldots\) \(S_N\)

  • The first line contains an integer \(N\) representing the number of seats.
  • The second line contains \(N\) integers \(S_1, S_2, \ldots, S_N\) separated by spaces, representing whether each seat is occupied. \(S_i = 1\) means seat \(i\) is occupied, and \(S_i = 0\) means it is vacant.

【输出】

Print in one line the maximum number of new guests that can be guided while satisfying the condition.

【输入样例】

5
0 0 1 0 0

【输出样例】

2

【核心思想】

  1. 问题分析:给定 \(N\) 个座位的初始状态 \(S_i\)\(1\) 表示已占用,\(0\) 表示空),要求在不移动已有客人的前提下,尽可能多地安排新客人,且最终不能存在三个连续的座位都被占据。这是一个贪心问题,关键在于从左到右遍历每个空座位,判断是否可以在不违反规则的前提下安排新客人。

  2. 算法选择

    • 贪心策略:从左到右遍历每个空座位,优先安排能安排的客人
    • 局部检查:对于每个空座位,检查其周围座位状态,判断是否会导致出现三个连续的 \(1\)
    • 即时标记:一旦确定可以安排,立即将座位标记为已占用,影响后续判断
  3. 关键步骤

    • 遍历座位\(i = 1\)\(N\)):
      • \(S_i = 1\)(已占用),跳过
      • 初始化 flag = true,表示当前座位可以安排
    • 冲突检查(三种情况会导致无法安排):
      • 情况1:左边和右边都已占用(\(S_{i-1} = 1\)\(S_{i+1} = 1\)),安排后会形成 1 1 1
      • 情况2:左边已有两个连续占用(\(S_{i-2} = 1\)\(S_{i-1} = 1\)),安排后会形成 1 1 1
      • 情况3:右边已有两个连续占用(\(S_{i+1} = 1\)\(S_{i+2} = 1\)),安排后会形成 1 1 1
    • 安排客人
      • flag = true,则 S_i = 1ans++
    • 输出 ans
  4. 时间/空间复杂度

    • 时间复杂度:\(O(N)\),只需遍历一次所有座位,每次检查为 \(O(1)\)
    • 空间复杂度:\(O(N)\),存储座位状态数组
  5. 贪心策略的核心思想

    • 局部最优:从左到右遍历,只要当前空座位不会导致出现三个连续的 \(1\),就立即安排新客人
    • 即时反馈:安排后立即修改座位状态,影响后续判断,确保全局满足条件
    • 三种冲突模式
      • 1 0 1 模式:中间安排会变成 1 1 1
      • 1 1 0 模式:右边安排会变成 1 1 1
      • 0 1 1 模式:左边安排会变成 1 1 1
    • 正确性保证:由于题目保证初始状态没有三个连续的 \(1\),且我们只在没有冲突时才安排,因此最终状态一定满足条件
    • 适用于约束条件局部化、贪心选择不影响全局最优的问题

【算法标签】

贪心

【代码详解】

#include <bits/stdc++.h>
using namespace std;
const int N = 200005;
int n, ans;
int s[N];  // 整数数组,存储座位状态:0表示空,1表示已占

int main()
{
    cin >> n;  // 输入座位数量

    // 读取n个整数的座位状态
    for (int i = 1; i <= n; i++)
    {
        cin >> s[i];
    }

    // 遍历每个座位
    for (int i = 1; i <= n; i++)
    {
        if (s[i] == 1)  // 如果当前座位已经有人,跳过
        {
            continue;
        }

        bool flag = true;  // 标记当前座位是否可以安排新客人

        // 情况1:检查是否形成"1 0 1"的模式,即左右座位都有人
        if (i + 1 <= n && s[i - 1] == 1 && s[i + 1] == 1)
        {
            flag = false;  // 不能安排,否则会形成"1 1 1"
        }
        // 情况2:检查左边是否已经有两个连续的1
        else if (i >= 3 && s[i - 2] == 1 && s[i - 1] == 1)
        {
            flag = false;  // 不能安排,否则会形成"1 1 1"
        }
        // 情况3:检查右边是否已经有两个连续的1
        else if (i + 2 <= n && s[i + 1] == 1 && s[i + 2] == 1)
        {
            flag = false;  // 不能安排,否则会形成"1 1 1"
        }

        // 如果当前座位可以安排新客人
        if (flag)
        {
            s[i] = 1;  // 将座位标记为已占用
            ans++;     // 增加安排的客人数量
        }
    }

    cout << ans << endl;  // 输出最大可安排的客人数量
    return 0;
}

【运行结果】

5
0 0 1 0 0
2
posted @ 2026-06-14 10:43  团爸讲算法  阅读(9)  评论(0)    收藏  举报