• POJ 1275/HDU 1529 Cashier Employment (差分约束)


    POJ链接
    HDU链接

    题意:一个商店,告诉你一天每个小时里至少需要的人数,以及来应聘的人数的工作的起始时间,固定工作8小时,求最少应该雇佣的人数。

    思路:设 s[i] 表示在前 i 小时,总开始工作的人数,所以, i>=8时, 有 s[i] - s[i-8] >= i时刻需要的人数,
    i<8 时, 有 s[i]+s[24]-s[i+16]>=i时刻需要的人数 。 同时,对于相邻时间会有 0<=s[i] - s[i-1]<=i时刻开始工作的人数。在这里会发现 s[24] 就是我们要求的答案,但就这样的话还是求不出,所以枚举s[24];

    想法:难点在建立不等式,即建图。(大佬厉害)

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <vector>
    #include <queue>
    const int maxn = 50;
    const int inf = 0x3f3f3f3f;
    using namespace std;
    struct note{
        int to, w;
        note(int to1, int w1){
            to = to1, w = w1;
        }
    };
    vector <note> maps[maxn];
    int need[maxn], work[maxn], ans;
    //need[i] i时刻需要的人数
    //work[i] i时刻开始工作的人数
    
    
    void init(){//要枚举答案, 所以每次要初始化,并建图
        for(int i=0; i<=24; i++)
            maps[i].clear();
        for(int i=1; i<=24; i++){
            maps[i-1].push_back(note(i, 0));	// s[i] - s[i-1] >= 0
            maps[i].push_back(note(i-1, -work[i]));
            //s[i] - s[i-1] <= work[i]  --->  s[i-1] - s[i] >= -work[i]
            if(i>=8)
                maps[i-8].push_back(note(i, need[i]));	//s[i] - s[i-8] >= need[i]
            else
                maps[16+i].push_back(note(i, need[i]-ans)); //s[i] - s[i+16] >= need[i]-ans
        }
        maps[0].push_back(note(24, ans));	//s[24]-s[0]>=ans  (容易忘记)
    }
    
    bool spfa(){
        int dis[maxn], cnt[maxn];
        //图有可能回出现负环, cnt[i] 记录 i 点入队列的次数
        bool vis[maxn];
        for(int i=0; i<=24; i++)
            dis[i] = -inf, vis[i] = false, cnt[i] = 1;
        dis[0] = 0, vis[0] = true, cnt[0] = 1;
        queue <int> q;
        q.push(0);
        while(!q.empty()){
            int u = q.front();
            q.pop();
            vis[u] = false;
            for(int i=0, len = maps[u].size(); i<len; i++){
                int v = maps[u][i].to, w = maps[u][i].w;
                if(dis[v] < dis[u] + w){
                    dis[v] = dis[u] + w;
                    if(!vis[v]){
                        cnt[v]++;
                        if(cnt[v] > 24)
                            return false; //存在负环,无解
                        vis[v] = true;
                        q.push(v);
                    }
                }
            }
        }
        if(dis[24] == ans)
            return true;
        return false;
    }
    
    int main()
    {
        int t;
        scanf("%d", &t);
        while(t--){
            for(int i=1; i<=24; i++){
                scanf("%d", &need[i]);
            }
            int n;
            scanf("%d", &n);
            for(int i=1; i<=n; i++){
                int j;
                scanf("%d", &j);
                work[j+1]++;
            }
            for(ans=0; ans<=n; ans++){ //枚举
                init();
                if(spfa()){
                    break;
                }
            }
            if(ans > n)
                printf("No Solution
    ");
            else
                printf("%d
    ", ans);
        }
        return 0;
    }
    
    
  • 相关阅读:
    [转]基于S2SH框架的项目—antlr-2.7.2.jar包冲突问题
    输入法那没有小键盘的图标解决方法
    Chrome百度不显示中文字体
    转:数据库范式(1NF 2NF 3NF BCNF)
    转:海明纠错码
    奇阶魔方阵
    字符串的模式匹配
    红黑树
    排序算法总结
    关于面试总结9-接口测试面试题
  • 原文地址:https://www.cnblogs.com/jizhihong/p/13337363.html
Copyright © 2020-2023  润新知