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

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

时间:2023-10-27 15:37:02浏览次数:41  
标签: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://blog.51cto.com/u_13536312/8057498

相关文章

  • AnyCAD程序无法启动的问题解决方法
    在某些电脑上会出现基于AnyCAD开发的程序无法启动的问题,如:System-ArgumentEcception:Pleasecheckthedependendes解决方法安装最新的VS运行时库,如VS2022:微软官方下载地址:x64:vc_redist.x64.exeSystem.AccessViolationException:"Attemptedtoreadorwriteprotectedmemor......
  • CF777题解
    分析先对每一列都做DP寻找极长单调不降区间,能够得到若干极长单调不降区间,只要询问的区间是这些区间的子区间,那么说明在这个区间内必有一列的这个区间是单调不降的。思考如何快速判断子区间。用\(f_{x}\)表示以\(x\)为所有左端点为\(x\)的区间的右端点最大值,那么对于......
  • ThinkPad OneLink+ Dock扩展坞 多屏幕 黑屏 问题解决
    我的机器是ThinkpadnewS2,扩展坞是ThinkPadOneLink+Dock,操作系统是win10原版。由于工作原因,把笔记本当台式机用。接了两台1920*1080的显示器。用了一段时间后,两台显示器中的其中一台显示器,黑屏,在win10的显示界面,应当有三台显示器,但实际只有两台。类似下图出现这个问题,毫无......
  • 'main' attribute cannot be used in a module that contains top-level code 问题解
    核心是@main注解在main.swift文件中,可以重新命名下参考资料https://stackoverflow.com/questions/73431031/swift-cli-app-main-attribute-cannot-be-used-in-a-module-that-contains-top-leve......
  • CF777A题解
    分析发现操作\(6\)次后就会回到初状态,于是将状态打表,将\(n\bmod6\)即可。代码#include<iostream>usingnamespacestd;constexprintMAXN(1000007);inta[6][3]={ {0,1,2}, {1,0,2}, {1,2,0}, {2,1,0}, {2,0,1}, {0,2,1}};intn,k;inli......
  • 在Jupyter notebooke中安装Nbextensions的问题解决办法
    问题1:使用命令行成功下载,但在Jupyternotebooke中不显示插件解决方案:找了很多方法,看到了一个简单有效的,决定一试,发现找不到路径,借助工具搜索匹配的路径,嘿嘿,找到了,但是匹配出来3个,都加上!再次打开Jupyter,终于看到插件。参考网站:jupyternotebook安装nbextension不显示问题_nbexte......
  • CF888G题解
    分析看到异或不难想到01Trie。不难想到,当两个数的值相等的时候,我们可以当这两个点是一个点,因为连边的费用为\(0\)。那么对于一个序列\(n\),若存在\(m\)种不同的权值,那么在Trie树上子节点数为\(2\)的节点就有\(m-1\)个(因为如果一个数新加进来与所有数都不同,那么一定......
  • P8865 [NOIP2022] 种花 题解
    前言去年多测不清空导致即便CCF放过了我的\(O(n^2m)\)的代码但依然挂成了\(0pts\)。当时看清空数组后能过CCF数据就没再管。时隔\(1\)年,重做这道题写了\(O(nm)\)的正解,终于完成了当年的心愿。\(O(n^2m)\)思路想到计算方案的话可以维护两个数组\(c1_{i,j}\)表......
  • SP4082 MBLAST - BLAST 题解
    几万年前做的dp题了,有亿点点水题意简述求一个字符串添加多少个空格距离最小解法求距离最小,可以考虑动规,其实这题的写法和最长公共子序列的写法类似。我们设\(f(i,j)\)表示\(a[1]\sima[i]\)和\(b[1]\simb[j]\)的距离不加空格的时候为\(f(i,j)=f(i-1,j-1)+\le......
  • [AGC061A] Long Shuffle 题解
    题意给定一个满足\(A_i=i\)的排列\(A\),求对其进行一次\(\mathrm{shuffle}(1,N)\)操作后其第\(K\)项的值。其中\(\mathrm{shuffle}(L,R)\)的定义如下:若\(R=L+1\),那么交换\(A_L\)和\(A_R\)的值否则,依次执行\(\mathrm{shuffle}(L,R-1)\),\(\mathrm{shuffle}(......