三十年河东,三十年河西|

自动机

园龄:1年10个月粉丝:2关注:4

Codeforces Round 893 (Div. 2)

B

题意:

有 n 个椅子,每个椅子编号为 1 - n, 其中有 m 个椅子上坐着一个卖饼的人,你需要从 1 走到 n,当你满足下面三个条件之一时你就要吃一块饼:

  1. 你在一号点时要吃一块饼
  2. 你距离上一次吃饼已经走过了 d 个椅子,那么你需要吃一块
  3. 当前椅子有一个卖饼人你需要吃一块
    你现在可以移除一个卖饼人,问你最少要吃多少饼,有多少种方案?(每个点位,最多吃一个,不重复计算)

思路:

先把一个人都不移的情况下要吃多少饼,然后枚举一下删除各个点的比一下大小

inline void solve() 
{
    int n, m, d; cin >> n >> m >> d;
    std::vector<int> s(m + 2);
    for (int i = 1; i <= m; i++) cin >> s[i];

    s[0] = 1, s[m + 1] = n + 1; // 因为一号点必吃一块,所以假设那里有个卖饼的,因为需要判断最后一个卖饼人离 n 的距离,所以在 n + 1 也假设一个
    
    int tot = 1;
    for (int i = 1; i <= m + 1; i++)
    {
        tot += (s[i] - s[i - 1] - 1) / d;  // 两次吃饼间隔 d 个椅子就吃一次
        if (s[i] != 1 && s[i] != n + 1) tot++; // 碰见卖饼人也要吃一个
    }

    int ans = inf, num = 0;
    for (int i = 1; i <= m; i++)
    {
        int t = tot;
        t -= (s[i] - s[i - 1] - 1) / d + (s[i + 1] - s[i] - 1) / d; // 删除s[i], 把他的贡献也删掉
        if (s[i] != 1) t -= 1;

        t += (s[i + 1] - s[i - 1] - 1) / d; // 删除之后间隔变大了,重新加上间隔吃饼数

        if (t < ans)
        {
            ans = t;
            num = 1;
        }
        else if (ans == t) num++;
    }

    cout << ans << ' ' << num << endl;
}

本文作者:自动机

本文链接:https://www.cnblogs.com/monituihuo/articles/17638590.html

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   自动机  阅读(5)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起