zoukankan      html  css  js  c++  java
  • 【差分约束】poj1275Cashier 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 of cashiers at different times of each day (for example, a few cashiers after midnight, and many in the afternoon) to provide good service to its customers, and he wants to hire the least number of cashiers for this job. 

    The manager has provided you with the least number of cashiers needed for every one-hour slot of the day. This data is given as R(0), R(1), ..., R(23): R(0) represents the least number of cashiers needed from midnight to 1:00 A.M., R(1) shows this number for duration of 1:00 A.M. to 2:00 A.M., and so on. Note that these numbers are the same every day. There are N qualified applicants for this job. Each applicant i works non-stop once each 24 hours in a shift of exactly 8 hours starting from a specified hour, say ti (0 <= ti <= 23), exactly from the start of the hour mentioned. That is, if the ith applicant is hired, he/she will work starting from ti o'clock sharp for 8 hours. Cashiers do not replace one another and work exactly as scheduled, and there are enough cash registers and counters for those who are hired. 

    You are to write a program to read the R(i) 's for i=0..23 and ti 's for i=1..N that are all, non-negative integer numbers and compute the least number of cashiers needed to be employed to meet the mentioned constraints. Note that there can be more cashiers than the least number needed for a specific slot. 

    Input

    The first line of input is the number of test cases for this problem (at most 20). Each test case starts with 24 integer numbers representing the R(0), R(1), ..., R(23) in one line (R(i) can be at most 1000). Then there is N, number of applicants in another line (0 <= N <= 1000), after which come N lines each containing one ti (0 <= ti <= 23). There are no blank lines between test cases.

    Output

    For each test case, the output should be written in one line, which is the least number of cashiers needed. 
    If there is no solution for the test case, you should write No Solution for that case. 

    Sample Input

    1
    1 0 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1
    5
    0
    23
    22
    1
    10
    

    Sample Output

    1

    题目大意

    直接挂loj的翻译算了……

    题目分析

    算是差分约束类型有难度并且挺经典的题目。

    设$s_i$为$i$时刻能够开始工作的人数;$x_i$为$i$时刻实际雇佣的人数。于是有$x_i≤num_i$。设$a_i$为$i$时刻至少需要工作的人数。有:

    $x_{i-7}+x_{i-6}+...+x_{i-1}+x_i≥a_i$

    设$t_i=x_1+x_2+...+x_i$,则得到

    $0≤t_i-t_{i-1}≤s_i,0≤i≤23,$

    $t_i-t_{i-8}≥a_i,8≤i≤23,$

    $t_{23}+t_i-t_{i+16}≥a_i,0≤i≤7$

    那么在建出约束关系之后,就是枚举$t_{23}$.

    之后就是处理的细节需要注意一下。

     1 #include<cstdio>
     2 #include<cctype>
     3 #include<cstring>
     4 const int maxn = 103;
     5 const int maxm = 303;
     6 
     7 struct Edge
     8 {
     9     int y,val;
    10     Edge(int a=0, int b=0):y(a),val(b) {}
    11 }edges[maxm];
    12 int T,n,ans,a[35],s[maxn],dis[maxn];
    13 int edgeTot,head[maxn],nxt[maxm];
    14 bool vis[maxn];
    15 
    16 int read()
    17 {
    18     char ch = getchar();
    19     int num = 0;
    20     bool fl = 0;
    21     for (; !isdigit(ch); ch=getchar())
    22         if (ch=='-') fl = 1;
    23     for (; isdigit(ch); ch=getchar())
    24         num = (num<<1)+(num<<3)+ch-48;
    25     if (fl) num = -num;
    26     return num;
    27 }
    28 void init()
    29 {
    30     edgeTot = 0;
    31     memset(dis, -0x3f3f3f3f, sizeof dis);
    32 //    memset(dis, 0, sizeof dis);
    33     memset(vis, 0, sizeof vis);
    34     memset(head, -1, sizeof head);
    35 }
    36 void addedge(int u, int v, int c)
    37 {
    38     edges[++edgeTot] = Edge(v, c), nxt[edgeTot] = head[u], head[u] = edgeTot;
    39 }
    40 bool dfs(int x)
    41 {
    42     vis[x] = 1;
    43     for (int i=head[x]; i!=-1; i=nxt[i])
    44     {
    45         int v = edges[i].y, w = edges[i].val;
    46         if (dis[v] < dis[x]+w){
    47             dis[v] = dis[x]+w;
    48             if (vis[v]||dfs(v)) return 1;
    49         }
    50     }
    51     vis[x] = 0;
    52     return 0;
    53 }
    54 bool check(int w)
    55 {
    56     init(), dis[0] = 0;
    57 //    for (int i=1; i<=23; i++) addedge(i-1, i, 0);addedge(23, 0, 0);
    58 //    for (int i=1; i<=23; i++) addedge(i, i-1, -w);addedge(0, 23, -w);
    59     for (int i=1; i<=24; i++) addedge(i-1, i, 0), addedge(i, i-1, -s[i]);
    60 //    for (int i=8; i<=23; i++) addedge(i-8, i, a[i]);
    61 //    for (int i=0; i<=7; i++) addedge(i+16, i, s[i]-w);    //注意细节处理
    62     for (int i=8; i<=24; i++) addedge(i-8, i, a[i]);
    63     for (int i=1; i<=8; i++) addedge(i+16, i, a[i]-w);
    64     addedge(0, 24, w);
    65     return dfs(0);
    66 }
    67 int main()
    68 {
    69     T = read();
    70     while (T--)
    71     {
    72         memset(s, 0, sizeof s);
    73         for (int i=1; i<=24; i++) a[i] = read();
    74         n = read(), ans = -1;
    75         for (int i=1; i<=n; i++) s[read()+1]++;
    76         for (int i=0; i<=n; i++)
    77             if (!check(i)){
    78                 ans = i;
    79                 break;
    80             }
    81         if (ans==-1) puts("No Solution");
    82         else printf("%d
    ",ans);
    83     }
    84     return 0;
    85 }

    END

  • 相关阅读:
    阿里Java完整学习资料
    Android 矢量图详解
    关于 Android 状态栏的适配总结
    SSM框架视频资料
    hideSoftInputFromWindow
    微信支付
    git+coding.net记录篇
    ClassNotFoundException超限
    react native初步常见问题
    React Native windows搭建记录
  • 原文地址:https://www.cnblogs.com/antiquality/p/9858318.html
Copyright © 2011-2022 走看看