HDU [1529] || POJ [P1275] Cashier Employment

经典的差分约束+二分答案。
本题的难点在于如何建图。
设x[i] 表示第i个小时可以开始工作的有多少个人。
num[i] 表示第i个小时最少需雇佣多少人。
s[i] 表示1...i小时实际开始工作的有多少人
因为最后要求的是s[24]的最小值,所以我们以s为中心建图。
因为我们求得是最小值,所以都转化成>=号的形式
我们逐步分析题目的已知条件:

  1. 第i小时实际开始工作的人数应小于等于可以开始的人数,即 $ s[i]-s[i-1]<=x[i] $ 变成 $ s[i-1]-s[i] >=-x[i] $
  2. 第i小时实际开始工作的人数应大于等于0,即$ s[i]-s[i-1]>=0 $ .
  3. 第i小时实际工作的人数应大于等于最少需雇佣的人数,即 $ s[i]-s[i-8]>=x[i] $ .
    当i>=8 时,$ s[i]-[i-8]>=x[i] $
    当i<8 时,$ s[24]+s[i]-s[i+16]>=x[i] $
    我们发现上式有三个变量,不符合差分约束的基本形式,我们可以二分答案,将上式变为 $ s[i]-s[i+16]>=x[i]-ans $
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <queue>
#include <ctime>
#define RST(a) memset((a),0,sizeof((a)))
using namespace std;
const int MAXN=50005;
int init(){
    int rv=0,fh=1;
    char c=getchar();
    while(c<'0'||c>'9'){
        if(c=='-') fh=-1;
        c=getchar();
    }
    while(c>='0'&&c<='9'){
        rv=(rv<<1)+(rv<<3)+c-'0';
        c=getchar();
    }
    return fh*rv;
}
struct edge{
    int to,nxt,dis;
}e[MAXN];
int T,head[MAXN],num[30],pre[30],x[30],nume,dis[30];
void adde(int from,int to,int dis){
    e[++nume].to=to;
    e[nume].dis=dis;
    e[nume].nxt=head[from];
    head[from]=nume;
}
bool SPFA(){
    for(int i=0;i<=29;i++) dis[i]=-0x3f3f3f3f;
    bool f[30];
    int cnt[30];
    RST(f);RST(cnt);
    queue <int> q;
    q.push(24);
    dis[24]=0;
    f[24]=1;
    while(!q.empty()){
        int u=q.front();q.pop();
        f[u]=0;
        for(int i=head[u];i;i=e[i].nxt){
            int v=e[i].to;
            if(dis[v]<dis[u]+e[i].dis){
                dis[v]=dis[u]+e[i].dis;
                if(!f[v]){
                    q.push(v);
                    f[v]=1;
                    cnt[v]++;
                    if(cnt[v]>=23) return 0;
                }
            }
        }
    }
    if(dis[0]==-0x3f3f3f3f) return 0;
    else return 1;
}
bool check(int mid){
    RST(e);RST(head);nume=0;RST(dis);
    for(int i=1;i<=24;i++){
        adde(i-1,i,0);
        adde(i,i-1,-x[i]);
        if(i>=8){
            adde(i-8,i,num[i]);
        }
    }
    for(int i=0;i<8;i++){
        adde(i+16,i,num[i]-mid);
    }
    if(SPFA()) return 1;
    else return 0;
}
int main(){
    //freopen("in.txt","r",stdin);
    srand(time(NULL));
    T=init();
    while(T--){
        RST(num);RST(x);RST(dis);RST(head);RST(e);
        nume=0;RST(pre);
        for(int i=0;i<=23;i++) num[i]=init();
        int n=init();
        for(int i=1;i<=n;i++){
            int t=init();
            x[t]++;
        }
        pre[0]=x[0];
        for(int i=1;i<=23;i++){
            pre[i]=pre[i-1]+x[i];
        }
        int l=0,r=n,mid=0;
        while(l<=r){
            mid=(l+r)/2;
            if(check(mid)){
                r=mid-1;
            }else l=mid+1;
        }
        if(l>=n) printf("No Solution\n");
        else printf("%d\n",l);
    }
    //fclose(stdin);
    return 0;
}

原文地址:https://www.cnblogs.com/Mr-WolframsMgcBox/p/8143245.html

时间: 2024-10-17 09:51:04

HDU [1529] || POJ [P1275] Cashier Employment的相关文章

图论(差分约束系统):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

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

poj 1275 Cashier Employment - 差分约束 - 二分答案

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 d

HDU 1087 &amp;&amp; POJ 2533(DP,最长上升子序列).

~~~~ 两道题的意思差不多,HDU上是求最长上升子序列的和,而POJ上就的是其长度. 貌似还有用二分写的nlogn的算法,不过这俩题n^2就可以过嘛.. ~~~~ 题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=1087 http://poj.org/problem?id=2533 ~~~~ HDU1087: #include<cstdio> #include<cstring> #include<algorithm> #

Eight hdu 1043 poj 1077

Description The 15-puzzle has been around for over 100 years; even if you don't know it by that name, you've seen it. It is constructed with 15 sliding tiles, each with a number from 1 to 15 on it, and all packed into a 4 by 4 frame with one tile mis

hdu 2844 poj 1742 Coins

hdu 2844 poj 1742 Coins 题目相同,但是时限不同,原本上面的多重背包我初始化为0,f[0] = 1;用位或进行优化,f[i]=1表示可以兑成i,0表示不能. 在poj上运行时间正好为时限3000ms....太慢了,hdu直接TLE(时限1s); 之 后发现其实并不是算法的问题,而是库函数的效率没有关注到.我是使用fill()按量初始化的,但是由于memset()可能是系统底层使用了四个字节拷 贝的函数(远比循环初始化快),效率要高得多..这就是为什么一直TLE的原因,fil

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

HDU 1829 &amp;&amp; POJ 2492 A Bug&#39;s Life(种类并查集)

题目地址:HDU 1829     POJ 2492 这个题可以用两种方法做,第一眼看完题是觉得用dfs染色判断二分图.然后又写的刚学的种类并查集.原来并查集可以这样用,真是神奇.. dfs染色代码: #include <iostream> #include <cstdio> #include <string> #include <cstring> #include <stdlib.h> #include <math.h> #incl