首页 > 其他分享 >Acwing393. 雇佣收银员 题解 差分约束

Acwing393. 雇佣收银员 题解 差分约束

时间:2023-09-20 11:55:55浏览次数:34  
标签:24 le 收银员 int 题解 ge maxn Acwing393 dis

题目链接:https://www.acwing.com/problem/content/description/395/

解题思路:

差分约束。

为了方便起见,定义第 \(i\) 个时间段为 \(i-1:00\) 到 \(i:00\) 这个时间段。

首先,为了方便开一个额外的点,令 \(R_i\) 对应为题目中的 \(R(i+1)\),即 \(R_i\) 表示 \(i-1:00\) 到 \(i:00\) 这个时间段的最小需求人数。即用 \(R_i\) 替代 \(R(i+1)\) 表示第 \(i\) 个时间段人数的需求量。

然后,统计一下每个时间段能够供给的最大人数,用 \(num_i\) 表示第 \(i\) 个时间段能够供给的最大人数。

用 \(x_i\) 表示第 \(i\) 个时间段需要分配的最小人数,可以得到以下式子:

  • \(0 \le x_i \le num_i\),①
  • \(x_{i-7} + x_{i-6} + \cdots + x_i \ge r_i\),②

上述这个式子不具有差分约束的一般性,所以开一个前缀和,定义 \(S_i = \sum\limits_{j=1}^i x_j\),上述不等式组转换为:

  • \(0 \le S_i - S_{i-1} \le num_i\),对任意 \(1 \le i \le 24\)
  • 当 \(8 \le i \le 24\) 时,有
    • \(S_i - S_{i-8} \ge r_i\)
  • 当 \(1 \le i \le 7\) 时,有
    • \(S_i + S_{24} - S_{i+16} \ge r_i\)

将上面这些式子重新梳理一下得:

  1. 对于任意 \(1 \le i \le 24\),有 \(S_i \ge S_{i-1} + 0\)
  2. 对于任意 \(1 \le i \le 24\),有 \(S_{i-1} \ge S_i - num_i\)
  3. 对于任意 \(8 \le i \le 24\),有 \(S_i \ge S_{i-8} + r_i\)
  4. 对于任意 \(1 \le i \le 7\),有 \(S_i \ge S_{i+16} + r_i - S_{24}\)

显然第 \(4\) 种情况还是不具有差分约束的一般性。

但是可以发现 \(S_{24} \le N \le 1000\),所以可以从 \(0\) 到 \(N\)枚举 \(S_{24}\) 的值,差分约束建图判断是否存在负环。不存在负环的最小的 \(S_{24}\) 就是我们所需的答案。

另外,因为 \(S_{24}\) 目前是一个固定值,所以我们还可以得到一个等式:

\(S_{24} = S_0 + C\)

其中 \(C\) 对应的就是 \(S_{24}\) 的固定的值。

所以,还需满足如下两个式子:

  • \(S_{24} \ge S_0 + C\)
  • \(S_0 \ge S_{24} - C\)

对应需要额外加两条边。

示例程序:

#include <bits/stdc++.h>
using namespace std;
const int maxn = 25;
struct Edge {
    int v, w;
};
vector<Edge> g[maxn];

int dis[maxn], cnt[maxn];
bool ins[maxn];
bool spfa() {
    stack<int> stk;
    memset(cnt, 0, sizeof(cnt));
    memset(ins, 0, sizeof(ins));
    memset(dis, -0x3f, sizeof(dis));
    dis[0] = 0;
    stk.push(0);
    while (!stk.empty()) {
        int u = stk.top();
        stk.pop();
        ins[u] = false;
        if (++cnt[u] >= 25)
            return false;
        for (auto e : g[u]) {
            int v = e.v, w = e.w;
            if (dis[v] < dis[u] + w) {
                dis[v] = dis[u] + w;
                if (!ins[v])
                    ins[v] = true, stk.push(v);
            }
        }
    }
    return true;
}

int T, r[maxn], N, num[maxn];

int cal() {
    for (int S24 = 0; S24 <= N; S24++) {
        for (int i = 0; i < 25; i++) g[i].clear();
        for (int i = 1; i <= 24; i++) {
            g[i-1].push_back({i, 0});
            g[i].push_back({i-1, -num[i]});
            if (i >= 8)
                g[i-8].push_back({i, r[i]});
            else
                g[i+16].push_back({i, r[i] - S24});
        }
        g[0].push_back({24, S24});
        g[24].push_back({0, -S24});
        if (spfa())
            return S24;
    }
    return -1;
}

int main() {
    scanf("%d", &T);
    while (T--) {
        for (int i = 1; i <= 24; i++)
            scanf("%d", r + i);
        memset(num, 0, sizeof(num));
        scanf("%d", &N);
        for (int i = 0; i < N; i++) {
            int t;
            scanf("%d", &t);
            t++;
            num[t]++;
        }
        int ans = cal();
        if (ans == -1)
            puts("No Solution");
        else
            printf("%d\n", ans);
    }
    return 0;
}

标签:24,le,收银员,int,题解,ge,maxn,Acwing393,dis
From: https://www.cnblogs.com/quanjun/p/17716970.html

相关文章

  • 微软自带拼音输入法不显示选字框的问题解决
    运行框、聊天框都不显示右击右下角的图标-设置-常规-兼容性拉到最下面有个“兼容性”,勾选即可现在OK了......
  • CF1767C Count Binary Strings 题解
    CF1767CCountBinaryStrings题解Foreword感谢@樱雪喵、@swiftc两位大佬的耐心指导。Links洛谷CodeforcesDescription有一个长度为\(n\)的01串\(s\)(下标从\(1\)开始)和一些限制\(a_{i,j}(1\lei\lej\len)\)。\(a_{i,j}\)的含义如下:\(a_{i,j}=\)含义......
  • 【POJ 3278】Catch That Cow 题解(深度优先搜索)
    农夫约翰已被告知一头逃亡奶牛的位置,并想立即抓住她。他从一条数字线上的N点(0≤N≤100000)开始,奶牛在同一条数字线上的K点(0≥K≤100000)。农夫约翰有两种交通方式:步行和坐车。*步行:FJ可以在一分钟内从任何点X移动到点X-1或X+1*坐车:FJ可以在一分钟内从任何X点移动到2×X点。如果奶......
  • 「2019 集训队互测 Day 3」操作序列计数 题解
    简化题意:对于每一个$L$,求出有多少个长度为$L+1$的非负整数序列$a$,满足$\sum_{i=0}^{L}a_ik^i\leqn$,并且$a_{L}>0$。我们注意题目要求的和是小于等于一个数,这不太方便。我们可以把它转化成和等于一个数的形式,其实就是和为$nk$的方案数,这就相当于在最后的和后面乘上一......
  • 【题解】CF1817 合集
    CF1817AAlmostIncreasingSubsequence考虑几乎上升的序列的长度,就是我们的区间长度减去\(a_{i-2}\geqa_{i-1}\geqa_i\)的对数,然后维护即可,当然个人感觉自己的代码有点长,可以考虑看洛谷题解代码code:#include<bits/stdc++.h>usingnamespacestd;constintNN=2e5+......
  • CF840C 题解
    一、题目描述:给你一个长度为$n$的序列$a_1\sima_n$,$0\lea_i\le1\times10^9$。求有多少种$1\simn$的全排列$b$,使得对于$i\in[2,n],a_{b_i}\timesa_{b_{i-1}}$不是完全平方数。本题中完全平方数的定义:若存在某个整数$k$,使得$k^2=x$,则$x$是一个......
  • 9.18CF1817题解
    9.18CF1817题解A.AlmostIncreasingSubsequence题意给定长度为\(n\)一个序列\(a\)以及\(q\)次询问,每次询问给出\(l\)和\(r\),找出序列\(a\)在\([l,r]\)内最长的几乎递增子序列。对于几乎递增的定义:如果一个序列中不存在连续的三个数\(x\),\(y\),\(z\),使得\(x\g......
  • 题解 AGC058B 【Adjacent Chmax】
    postedon2022-08-1500:08:56|under题解|sourceproblem一个长为\(n\)的排列\(P\),每次可以选择一个\(i\),令\(v=\max(P_i,P_{i+1})\),使\(P_i=P_{i+1}=v\),求若干次操作后有多少种不同的序列。\(1\leqn\leq5000\)。solution显然地,对于一个\(P_i\),它要么被完全覆盖......
  • AT_arc165_d 题解
    AT_arc165_d[ARC165D]SubstringComparison题解Links洛谷AtCoderDescription给定正整数\(n,m\)和\(m\)个形如\((A_{i},B_{i},C_{i},D_{i})\)的限制条件。判断是否存在一个长度为\(n\)的序列\(P\)满足\(\foralli\in[1,m]\),\(P_{A_{i}\dotsB_{i}}\)字典序......
  • AT_arc165_b 题解
    AT_arc165_b[ARC165B]SlidingWindowSort2题解Links洛谷AtCoderDescription给定正整数\(n,k\)和一个长度为\(n\)的整数\(P\),你需要选择一个长度为\(k\)的区间\([l,l+k-1]\),将这个区间从小到大排序。找到操作后最终字典序最大的排列。\(1\leqk\leqn\l......