1 条题解

  • 0
    @ 2025-4-7 23:49:39

    题目大意:给出24个数,第i个数表示在(i,i+1)小时内需要的人数,之后m个数,代表m个人前来应聘,其中每个人工作连续的8小时,给出应聘的人开始工作的时间,问最少需要雇佣的人数(可以在某个时间段中人数多于需要的人数)

    差分约束:

    1、题目需要求什么,就找什么之间的关系(二项式),比如,题目求雇佣的人数,就找出雇佣人数之间的关系,s[i]代表从0到i一共雇佣的人数

    2、注意0的问题,和总和的问题。

    3、判断的问题,不能存在环,和不能违背要求的值

    又因为题中雇佣人数会形成一个环,所以可以虚拟一个节点k,代表最初的节点 s[k] = 0

    那么归结关系有

    s[i]:0到i时刻雇佣的总人数,h[i]:i时刻;来应聘的人数,r[i]:i时刻需要的人数

    设:需要的人数为sum

    s[i] - s[i-1] >= 0

    s[i] - s[i-1] <= h[i] ;

    总数:s[23] - s[k] >= sum

    s[i] - s[i-8] >= r[i] (i >= 8)

    sum - s[i+16] + s[i] >= r[i] (i < 8)

    #include <cstdio>
    #include <cstring>
    #include <queue>
    #include <algorithm>
    using namespace std;
    #define INF 0x3f3f3f3f
    
    struct node {
        int v, w;
        int next;
    } edge[1000];
    
    int head[50], cnt;
    int r[30], h[30];
    int dis[30], vis[30];
    
    void add(int u, int v, int w) {
        edge[cnt].v = v;
        edge[cnt].w = w;
        edge[cnt].next = head[u];
        head[u] = cnt++;
    }
    
    int spfa(int sum) {
        memset(vis, 0, sizeof(vis));
        memset(dis, -INF, sizeof(dis));
        int u, v, i, num = 0;
        queue<int> que;
        while (!que.empty()) que.pop();
        vis[24] = 1;
        dis[24] = 0;
        que.push(24);
        while (!que.empty()) {
            u = que.front();
            que.pop();
            vis[u] = 0;
            for (i = head[u]; i != -1; i = edge[i].next) {
                v = edge[i].v;
                if (dis[v] < dis[u] + edge[i].w) {
                    dis[v] = dis[u] + edge[i].w;
                    num++;
                    if (vis[v] == 0) {
                        que.push(v);
                        vis[v] = 1;
                    }
                }
            }
            if (num > 1000) return 0;
        }
        if (dis[23] == sum) return 1;
        return 0;
    }
    
    int solve(int sum) {
        memset(head, -1, sizeof(head));
        cnt = 0;
        int i; // 这里删除了未使用的变量 j
    
        add(24, 0, 0);
        add(0, 24, -h[0]);
        add(24, 23, sum);
        for (i = 1; i <= 23; i++) {
            add(i - 1, i, 0);
            add(i, i - 1, -h[i]);
        }
        for (i = 0; i <= 23; i++) {
            if (i >= 8)
                add(i - 8, i, r[i]);
            else
                add(i + 16, i, r[i] - sum);
        }
        if (spfa(sum)) return 1;
        return 0;
    }
    
    int main() {
        int t, i, j, m;
        scanf("%d", &t);
        while (t--) {
            memset(h, 0, sizeof(h));
            for (i = 0; i <= 23; i++)
                scanf("%d", &r[i]);
            scanf("%d", &m);
            for (i = 0; i < m; i++) {
                scanf("%d", &j);
                h[j]++;
            }
            for (i = 0; i <= m; i++)
                if (solve(i))
                    break;
            if (i <= m)
                printf("%d\n", i);
            else
                printf("No Solution\n");
        }
        return 0;
    }
    • 1

    信息

    ID
    276
    时间
    1000ms
    内存
    256MiB
    难度
    10
    标签
    递交数
    12
    已通过
    1
    上传者