• POJ


    · 对于差分约束,题目要求求什么便设什么,令$Sum[i]$表示由$0 ~ i$的雇佣人数。

    · 要充分利用题目所给条件,令$Have[i]$表示i时刻申报的人数,$Need[i]$表示i时刻需要的人数「结合 “人数” 关键词」。

    此时容易列出两个基本不等式:

        Sum[i] - Sum[i - 1] >= 0;

       Sum[i] - Sum[i - 1] <= Have[i];

    此时发现还有$Need[]$和范围为8个单位长度的区间没有使用,可得:

        Sum[i] - Sum[i - 8] >= Need[i]; (i >= 8)

    那么还有环形无法处理。

    对于环形的处理:

    将整个$24$个单位的区间以当前点为分割点,将大区间分割为$(i - 8 + 24)$ ~ $i$ (环形)以及$i$ ~ $i + 16$,相当于覆盖了整个环形区间。

    相当于是去限制非当前考虑的完整的区间从而达到限制当前因环形而断开的区间。

    所以此时仅需考虑两个区间间的限制即可。

    并且需要一个$Sum[- 1]$。

    答案显然满足单调性,故考虑二分。

    令$mid$表示需要$mid$个服务员。

    则可列方程:

        mid - (Sum[i + 16] - Sum[i]) >= Need[i]; (i < 8)

    即可解答。

    · 代码:

      1 #include <iostream>
      2 #include <cstdio>
      3 #include <cstring>
      4 #include <queue>
      5 
      6 using namespace std;
      7 
      8 const int MAXN = 1000 + 10;
      9 const int MAXM = MAXN * 10;
     10 const int MAXT = 24 + 10;
     11 
     12 struct LinkedForwardStar {
     13     int to;
     14     int w;
     15 
     16     int next;
     17 } ;
     18 
     19 LinkedForwardStar Link[MAXM << 1];
     20 int Head[MAXT]= {0};
     21 int size = 0;
     22 
     23 void Insert (int u, int v, int w) {
     24     Link[++ size].to = v;
     25     Link[size].w = w;
     26     Link[size].next = Head[u];
     27 
     28     Head[u] = size;
     29 }
     30 
     31 int T;
     32 
     33 int N;
     34 
     35 int Have[MAXT];
     36 int Need[MAXN];
     37 
     38 int Dist[MAXT];
     39 int Count[MAXT];
     40 
     41 queue<int> Que;
     42 bool Inque[MAXT];
     43 
     44 bool SPFA (int mid) {
     45     memset (Dist, 0xcf, sizeof (Dist));
     46     memset (Count, 0, sizeof (Count));
     47     memset (Inque, 0, sizeof (Inque));
     48     while (! Que.empty())
     49         Que.pop();
     50 
     51     Que.push(24);
     52     Inque[24] = true;
     53     Dist[24] = 0;
     54 
     55     while (! Que.empty()) {
     56         int u = Que.front();
     57         Que.pop();
     58 
     59         Inque[u] = false;
     60         Count[u] ++;
     61 
     62         if (Count[u] >= 25)
     63             return false;
     64 
     65         for (int i = Head[u]; i; i = Link[i].next) {
     66             int v = Link[i].to, w = Link[i].w;
     67 
     68             if (Dist[u] + w > Dist[v]) {
     69                 Dist[v] = Dist[u] + w;
     70 
     71                 if (! Inque[v]) {
     72                     Que.push(v);
     73                     Inque[v] = true;
     74                 }
     75             }
     76         }
     77     }
     78 
     79     return Dist[23] == mid;
     80 }
     81 
     82 bool Check (int mid) {
     83     memset (Head, 0, sizeof (Head));
     84     size = 0;
     85 
     86     Insert (24, 23, mid);
     87     Insert (24, 0, 0);
     88     Insert (0, 24, - Have[0]);
     89     for (int i = 1; i <= 23; i ++) {
     90         Insert (i - 1, i, 0);
     91         Insert (i, i - 1, - Have[i]);
     92     }
     93     for (int i = 8; i <= 23; i ++)
     94         Insert (i - 8, i, Need[i]);
     95     for (int i = 0; i < 8; i ++)
     96         Insert (i + 16, i, Need[i] - mid);
     97 
     98     return SPFA (mid);
     99 }
    100 
    101 int main () {
    102     scanf ("%d", & T);
    103 
    104     for (int Case = 1; Case <= T; Case ++) {
    105         memset (Have, 0, sizeof (Have));
    106 
    107         for (int i = 0; i <= 23; i ++)
    108             scanf ("%d", & Need[i]);
    109 
    110         scanf ("%d", & N);
    111 
    112         for (int i = 1; i <= N; i ++) {
    113             int start;
    114             scanf ("%d", & start);
    115 
    116             Have[start] ++;
    117         }
    118 
    119         bool flag = false;
    120         int left = 0, right = N;
    121         while (left < right) {
    122             int mid = (left + right) >> 1;
    123 
    124             if (Check (mid)) {
    125                 flag = true;
    126                 right = mid;
    127             }
    128             else
    129                 left = mid + 1;
    130         }
    131 
    132         if (! flag)
    133             puts ("No Solution");
    134         else
    135             printf ("%d
    ", left);
    136     }
    137 
    138     return 0;
    139 }
    140 
    141 /*
    142 1
    143 1 0 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1
    144 5
    145 0
    146 23
    147 22
    148 1
    149 10
    150 */
    View Code
  • 相关阅读:
    typescript提示implicitly has an 'any' type 问题
    element-ui中的table可分页多选功能-记住上一页勾选数据
    CSS加载会阻塞页面显示?
    网络流(EK算法)
    网络流(dinic算法)
    洛谷p1120小木棍(剪枝优化)
    三种背包模板
    HDU2089-不要62(数位dp)
    windy数(数位dp)
    素数判定(待填坑)
  • 原文地址:https://www.cnblogs.com/Colythme/p/9696565.html
Copyright © 2020-2023  润新知