【题解】ZOJ1420 Cashier Employment

  论文——冯威《浅析差分约束系统》。

  论文讲得很详细,就不解释了。主要想记录一下对于差分约束的理解(感觉以前的学习真的是在囫囵吞枣啊……)

  差分约束系统,同于解决线性的不等关系是否存在合法解 & 求得最大 / 最小解。当其中牵涉到的式子形如 \(A[i] - A[i - 1] >= (<=) x\) 时,就可以运用差分约束求解了。处理的方法是由于这个式子为三角形不等式,即spfa中的松弛操作,所以我们看做一个图论的问题,跑最长路 \ 最短路即可。连边的方式自己画图感知就好了。

  当需要求解最大 / 最小值时:最大值运用最短路,最小值运用最长路。以求最大值为例:一个数能够取得的最大值即在满足了最小的约束情况下可以取得的最大值,而道路边权即为约束边,所以为最短路。

  通用解法:1.罗列出不等关系(注意要找全了)。2.移项,未知数一边,常数一边。3.考虑运用最长路 / 最短路求解。这题主要在于构建出方程与函数来描述不等关系的特征,当常数中有未知项时,可以考虑枚举求解(其实这个思想很重要,数据范围小的时候一定考虑枚举暴力呀)。当然这题由于满足单调性,所以二分一下~

#include <bits/stdc++.h>
using namespace std;
#define maxn 300000
int cnp = 1, head[maxn], num[maxn];
int R[maxn], dis[maxn], in[maxn];
bool vis[maxn];

struct edge
{
    int to, last, co;
}E[maxn];

int read()
{
    int x = 0, k = 1;
    char c;
    c = getchar();
    while(c < ‘0‘ || c > ‘9‘) { if(c == ‘-‘) k = -1; c = getchar(); }
    while(c >= ‘0‘ && c <= ‘9‘) x = x * 10 + c - ‘0‘, c = getchar();
    return x * k;
}

void add(int u, int v, int w)
{
    E[cnp].to = v, E[cnp].co = w;
    E[cnp].last = head[u], head[u] = cnp ++;
}

bool spfa()
{
    queue <int> q;
    for(int i = 1; i <= 30; i ++)
        dis[i] = -99999999;
    memset(vis, 0, sizeof(vis));
    memset(in, 0, sizeof(in));
    dis[0] = 0, q.push(0);
    while(!q.empty())
    {
        int u = q.front(); q.pop();
        vis[u] = 0;
        for(int i = head[u]; i; i = E[i].last)
        {
            int v = E[i].to;
            if(dis[v] < dis[u] + E[i].co)
            {
                dis[v] = dis[u] + E[i].co;
                if(!vis[v])
                {
                    if(++ in[v] == 26) return 1;
                    vis[v] = 1; q.push(v);
                }
            }
        }
    }
    return 0;
}

void Build(int mid)
{
    memset(head, 0, sizeof(head)); cnp = 1;
    for(int i = 1; i <= 24; i ++)
    {
        add(i - 1, i, 0);
        add(i, i - 1, -num[i]);
    }
    for(int i = 8; i <= 24; i ++)
        add(i - 8, i, R[i]);
    for(int i = 1; i < 8; i ++)
        add(i + 16, i, R[i] - mid);
    add(0, 24, mid);
}

int main()
{
    int T = read();
    while(T --)
    {
        for(int i = 1; i <= 24; i ++) R[i] = read();
        int n = read();
        memset(num, 0, sizeof(num));
        for(int i = 1; i <= n; i ++)
        {
            int x = read();
            num[x + 1] ++;
        }
        Build(n);
        if(spfa())
        {
            printf("No Solution\n");
            continue;
        }
        int l = 0, r = n, ans;
        while(l <= r)
        {
            int mid = (l + r) >> 1;
            Build(mid);
            if(spfa()) l = mid + 1;
            else ans = mid, r = mid - 1;
        }
        printf("%d\n", ans);
    }
    return 0;
}

原文地址:https://www.cnblogs.com/twilight-sx/p/9180853.html

时间: 2024-11-06 01:03:15

【题解】ZOJ1420 Cashier Employment的相关文章

POJ1275 Cashier Employment[差分约束系统 || 单纯形法]

Cashier Employment Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 7997   Accepted: 3054 Description A supermarket in Tehran is open 24 hours a day every day and needs a number of cashiers to fit its need. The supermarket manager has hir

图论(差分约束系统):POJ 1275 Cashier Employment

Cashier Employment Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 7651   Accepted: 2886 Description A supermarket in Tehran is open 24 hours a day every day and needs a number of cashiers to fit its need. The supermarket manager has hir

poj——1275 Cashier Employment 差分约束系统

Cashier Employment Description A supermarket in Tehran is open 24 hours a day every day and needs a number of cashiers to fit its need. The supermarket manager has hired you to help him, solve his problem. The problem is that the supermarket needs di

Cashier Employment(poj1275

Cashier Employment Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 9205   Accepted: 3564 Description A supermarket in Tehran is open 24 hours a day every day and needs a number of cashiers to fit its need. The supermarket manager has hir

POJ1275/ZOJ1420/HDU1529 Cashier Employment (差分约束)

转载请注明出处: http://www.cnblogs.com/fraud/          ——by fraud 题意:一商店二十四小时营业,但每个时间段需求的出纳员不同,现有n个人申请这份工作,其可以从固定时间t连续工作八个小时,问在满足需求的情况下最小需要多少个出纳 一道十分经典的差分约束题目,在构图上稍有难度 为避免负数,时间计数1-24. 令: r[i]表示i时间需要的人数 (1<=i<=24) num[i]表示i时间应聘的人数 (1<=i<=24) x[i]表示i时间

POJ1275 Cashier Employment 【二分 + 差分约束】

题目链接 POJ1275 题解 显然可以差分约束 我们记\(W[i]\)为\(i\)时刻可以开始工作的人数 令\(s[i]\)为前\(i\)个时刻开始工作的人数的前缀和 每个时刻的要求\(r[i]\),可以通过如下限制满足: \[s[i] - s[i - 8] \ge r[i]\] \[0 \le s[i] - s[i - 1] \le W[i]\] 但是\(i - 8\)可能为负,回到上一天的时刻,导致区间不连续,不好处理 我们可以二分答案\(sum\) 将\(i < 8\)的部分改为: \[

HDU-1529 Cashier Employment

据网上说这是到差分约束四星题... 可我觉得难吗? 比推DP方程容易... 两种约束方式,当然实现到程序就变成六种了... #include <cstdio> #include <cstdlib> #include <cstring> #include <cmath> #include <algorithm> #include <fstream> #include <iostream> #include <deque

poj 1275 Cashier Employment 差分约束

差分约束模板题,差分约束是判断联立不等式组是否有解的一种方法,建图是关键. 代码: //poj 1275 //sep9 #include <iostream> #include <queue> using namespace std; const int maxM=10024; const int maxN=32; struct Edge { int v,w,nxt; }edge[maxM]; int t[maxN],c[maxN],head[maxN],vis[maxN],inq

【POJ1275】Cashier Employment

题目: Description A supermarket in Tehran is open 24 hours a day every day and needs a number of cashiers to fit its need. The supermarket manager has hired you to help him, solve his problem. The problem is that the supermarket needs different number