zoukankan      html  css  js  c++  java
  • POJ1275 Cashier Employment 二分、差分约束

    传送门

    题意太长


    为了叙述方便,将题意中的$0$点看作$1$点,$23$点看做$24$点

    考虑二分答案(其实从小到大枚举也是可以的)

    设$x_i$是我们选的雇员第$i$小时开始工作的人数,$s_i$是$x_i$的前缀和,又设$p_i$为可以在第$i$小时开始工作的人数,$q_i$表示第$i$小时需要的人数,$mid$为我们二分的答案

    那么我们有

    $$s_i-s_{i-8} geq q_i , 8 leq i leq 24$$

    $$s_i - s_{i+16} geq q_i - mid , 1 leq i leq 7$$

    $$s_{i - 1} - s_i geq -p_i$$

    $$s_i - s_{i-1} geq 0$$(很容易漏掉)

    $$s_{24}-s_{0} geq mid$$

    最后一条边的原因是:注意到第二种边中我们强制了$s_{24} = mid$,但是实际跑出来的解有可能$s_{24} eq mid$,那么第二个式子就很有可能不成立。但是当$mid < s_{24}$时令$mid = s_{24}$时条件显然仍然成立,所以我们只需要让$s_{24} < mid$的时候强制让$s_{24} geq mid$才行。

    直接差分约束求最长路就完了

    差分约束有很多细节需要注意,掉了很多次坑qwq(比如每一次的queue都要清空)

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<queue>
     4 #include<cstring>
     5 #include<algorithm>
     6 using namespace std;
     7 
     8 inline int read(){
     9     int a = 0;
    10     bool f = 0;
    11     char c = getchar();
    12     while(c != EOF && !isdigit(c)){
    13         if(c == '-')
    14             f = 1;
    15         c = getchar();
    16     }
    17     while(c != EOF && isdigit(c)){
    18         a = (a << 3) + (a << 1) + (c ^ '0');
    19         c = getchar();
    20     }
    21     return f ? -a : a;
    22 }
    23 
    24 struct Edge{
    25     int end , upEd , w;
    26 }Ed[25*25];
    27 int num[25] , x[25] , maxDis[25] , flo[25] , head[25] , cntEd , preHead[25] , preCnt;
    28 queue < int > q;
    29 bool inq[25];
    30 
    31 inline void addEd(int a , int b , int c){
    32     Ed[++cntEd].end = b;
    33     Ed[cntEd].upEd = head[a];
    34     Ed[cntEd].w = c;
    35     head[a] = cntEd;
    36 }
    37 
    38 inline bool check(int mid){
    39 while(!q.empty())q.pop();
    40     memcpy(head , preHead , sizeof(preHead));
    41     cntEd = preCnt;
    42     for(int i = 1 ; i <= 8 ; i++)
    43         addEd(i + 16 , i , num[i] - mid);
    44     addEd(0 , 24 , mid);
    45     memset(maxDis , -0x3f , sizeof(maxDis));
    46     memset(inq , 0 , sizeof(inq));
    47     memset(flo , 0 , sizeof(flo));
    48     maxDis[0] = 0;
    49     q.push(0);
    50     while(!q.empty()){
    51         int t = q.front();
    52         q.pop();
    53         inq[t] = 0;
    54         for(int i = head[t] ; i ; i = Ed[i].upEd)
    55             if(maxDis[Ed[i].end] < maxDis[t] + Ed[i].w){
    56                 maxDis[Ed[i].end] = maxDis[t] + Ed[i].w;
    57                 if((flo[Ed[i].end] = flo[t] + 1) >= 24)
    58                     return false;
    59                 if(!inq[Ed[i].end]){
    60                     inq[Ed[i].end] = 1;
    61                     q.push(Ed[i].end);
    62                 }
    63             }
    64     }
    65     return true;
    66 }
    67 
    68 int main(){
    69 #ifdef LG
    70     freopen("1275.in" , "r" , stdin);
    71 #endif
    72     for(int T = read() ; T ; T--){
    73         for(int i = 1 ; i <= 24 ; i++)
    74             num[i] = read();
    75         cntEd = 0;
    76         memset(head , 0 , sizeof(head));
    77         memset(x , 0 , sizeof(x));
    78         int P = read() , L = 0 , R = P + 1;
    79         for(int i = P ; i ; i--)
    80             x[read() + 1]++;
    81         for(int i = 0 ; i < 24 ; i++)
    82             addEd(i , i + 1 , 0);
    83         for(int i = 8 ; i <= 24 ; i++)
    84             addEd(i - 8 , i , num[i]);
    85         for(int i = 1 ; i <= 24 ; i++)
    86             addEd(i , i - 1 , -x[i]);
    87         memcpy(preHead , head , sizeof(head));
    88         preCnt = cntEd;
    89         while(L < R){
    90             int mid = L + R >> 1;
    91             check(mid) ? R = mid : L = mid + 1;
    92         }
    93         if(L > P)
    94             puts("No Solution");
    95         else
    96             cout << L << endl;
    97     }
    98     return 0;
    99 }
  • 相关阅读:
    js如何识别后端返回的“↵”,让其换行
    ReactNative插件
    ReactNative踩坑
    js对当前时间进行处理
    vue-awesome-swiper手动滑动后不再自动轮播的问题
    HTML5知识点汇总
    懒加载的实现原理及一些实现方法
    使用node.js实现多人聊天室(socket.io、B/S)
    [vue学习] 卡片展示分行功能简单实现
    [vue学习]快速搭建一个项目
  • 原文地址:https://www.cnblogs.com/Itst/p/9867664.html
Copyright © 2011-2022 走看看