POJ1275 很好地差分约束系统 xingxing在努力

  还是花费了几天A这道题的, 蛮好的一道题, 题意是有一家咖啡店在二十四小时内每个小时段都需要一定数目的服务员来提供服务, 有n个应聘者来来这家店(一旦应聘者从第i小时开始工作那么他就要连续的工作八个小时), 现在给定应聘者的数量问你最少需要多少个服务员能满足这家店的需求。

  假设r[i]是这家店第i到第i+1小时所需要的服务员的最小数目,t[i]表示第i时刻来应聘的人数, s[i]表示前i个小时段内店铺招的总人数那么就可以得到下面的约束公式:

     0=<s[i] - s[i-1]<=t[i]     第i个时段内招的人数大于等于0 且 小于等于来应聘的人的数量

       s[i] – s[i-8] >= r[i], 8 <= i <= 24

s[i] – s[i+16] >= r[i] – s[24],  1<= i <= 7

     在这个定义下我们要求解的答案就是min(s[24] - s[0]), 由于s[24]未知因此我们枚举s[24]然后在判断即可, 由于求解出来的s[24]可能会小于ans(枚举值)所以我们在加上一个条件s[24] >=ans即可。代码如下:

#include <cstdio>
#include <algorithm>
#include <cstring>
#include <vector>
#include <queue>

using namespace std;
const int inf = 0x3f3f3f3f;
int r[30], t[30];
int n;

struct edge
{
    int v, cost;
    edge() {}
    edge(int v, int cost):v(v), cost(cost){}
};
vector<edge> G[30];
void build(int ans)
{
    for(int i=0; i<=24; i++) G[i].clear();
    G[0].push_back(edge(24, ans));
    for(int i=1; i<=24; i++)
    {
        G[i-1].push_back(edge(i, 0));
        G[i].push_back(edge(i-1, -t[i]));
    }
    for(int i=1; i<=7; i++)
        G[i+16].push_back(edge(i, r[i]-ans));
    for(int i=8; i<=24; i++)
        G[i-8].push_back(edge(i, r[i]));
}

int inque[30], dist[30], _count[30];

int spfa(int ans)
{
    memset(inque, 0, sizeof(inque));
    memset(_count, 0, sizeof(_count));
    for(int i=0; i<=24; i++) dist[i] = -inf;
    queue<int> que;
    dist[0] = 0;
    que.push(0);
    inque[0] = 1;
    while(!que.empty())
    {
        int u = que.front(); que.pop();
        //if(++_count[u] > 24) return false;
        inque[u] = 0;         //不要忘记置0,wa了n发
        for(int i=0; i<G[u].size(); i++)
        {
            edge e = G[u][i];
            int v = e.v, c = e.cost;
            if(dist[v] < dist[u]+c)
            {
                dist[v] = dist[u]+c;
                if(!inque[v])
                {
                    inque[v] = 1;
                    que.push(v);
                    if(++_count[v] > 24) return false;
                }
            }
        }
    }
    if(dist[24] == ans)
        return true;
    return false;
}

int main()
{
    int T;
    scanf("%d", &T);
    while(T--)
    {
        memset(r, 0, sizeof(r));
        memset(t, 0, sizeof(t));
        for(int i=1; i<=24; i++)
            scanf("%d", &r[i]);
        scanf("%d", &n);
        for(int i=0; i<n; i++)
        {
            int a;
            scanf("%d", &a);
            a++;
            t[a]++;
        }

        int ans = -1;
        for(int i=0; i<=n; i++)
        {
            build(i);
            if(spfa(i))
            {
                ans = i;
                break;
            }
        }
        if(ans == -1)
            printf("No Solution\n");
        else
            printf("%d\n", ans);
    }
    return 0;
}

  

  

时间: 2024-10-03 23:53:10

POJ1275 很好地差分约束系统 xingxing在努力的相关文章

bzoj 2330: [SCOI2011]糖果 差分约束系统

题意:幼儿园里有N个小朋友,lxhgww老师现在想要给这些小朋友们分配糖果,要求每个小朋友都要分到糖果.但是小朋友们也有嫉妒心,总是会提出一些要求,比如小明不希望小红分到的糖果比他的多,于是在分配糖果的时候,lxhgww需要满足小朋友们的K个要求.幼儿园的糖果总是有限的,lxhgww想知道他至少需要准备多少个糖果,才能使得每个小朋友都能够分到糖果,并且满足小朋友们所有的要求. 分析:很明显的差分约束系统. 由于是求最小值,所以就要把所有不等式都转换成x-y>=k的形式然后连一条y->x权值为k

差分约束系统

差分约束系统是指一系列不等式: $$ X_j - X_i \le C_{ij}(1\le i, j \le n) $$ 当然 i,j 不必取遍 1-n,而且在扩展的状况下,对于每个(i,j),可以由多个 $C_{ij}$,但是我们很容易把它们化成一个不等式. 在求解不等式组之前,我们可以分析一下这个不等式组的性质. 1. 这个不等式组是可以无解的,比如: $$X_1 - X_2 \le -1 \\ X_2 - X_3 \le -1 \\ X_3 - X_1 \le -1$$ 否则三个不等式相加得

UVa 515 - King (差分约束系统 + SPFA求带负权最短路)

下面是差分约束系统的详细介绍,以及解决方法~ 摘抄自 xuezhongfenfei(他好像也是转的....) 差分约束系统 X1 - X2 <= 0 X1 - X5 <= -1 X2 - X5 <= 1 X3 - X1 <= 5 X4 - X1 <= 4 X4 - X3 <= -1 X5 - X3 <= -3 X5 - X4 <= -3 不等式组(1) 全都是两个未知数的差小于等于某个常数(大于等于也可以,因为左右乘以-1就可以化成小于等于).这样的不等式组

差分约束系统 初见

今天初次学习差分约束系统,很神奇的东西 定义: 如果一个系统由n个变量和m个约束条件组成,其中每个约束条件形如xj-xi<=bk(i,j∈[1,n],k∈[1,m]),则称其为差分约束系统(system of difference constraints).亦即,差分约束系统是求解关于一组变量的特殊不等式组的方法. 求解差分约束系统,可以转化成图论的单源最短路径(或最长路径)问题. 其实在一些问题中需求最小值或最大值,同时需要满足一系列的不等式关系,这样就可以用到差分约束系统了,对于求最小值的问

POJ 2983 Is the Information Reliable?(差分约束系统)

题目地址:POJ 2983 这题刚上来完全不知道跟差分约束系统有什么关系.....后来发现只要判个负环就可以.. 因为假如有冲突的话会形成一个负环.之所以建图加上一个正值一个负值,是因为这样的话,像1 2 4和1 2 3这样的数据就会形成一个负环.这个方法还是很巧妙的...然后对于V的那些不清楚的位置,就会跟P的那些等式联立形成一个不等式,然后在用最短路判环的过程中就用松弛来解决. 代码如下: #include <iostream> #include <cstdio> #inclu

UVA 11374 Halum (差分约束系统,最短路)

题意:给定一个带权有向图,每次你可以选择一个结点v 和整数d ,把所有以v为终点的边权值减少d,把所有以v为起点的边权值增加d,最后要让所有的边权值为正,且尽量大.若无解,输出结果.若可无限大,输出结果.否则,输出最小边权的最大值. 思路:差分约束系统用最短路来解.列式子后建图,新图的边就是原图的边,权值也不变.有3种情况,要分开判断. (1)若连最小的权值1都达不到,肯定无解. (2)若可以超过所给边的最大权值,那么最小权值肯定可以继续增大. (3)接下来用二分猜答案,答案范围在[1,big]

POJ 3169 Layout(差分约束系统)

题目链接:http://poj.org/problem?id=3169 题意:n头牛编号为1到n,按照编号的顺序排成一列,每两头牛的之间的距离 >= 0.这些牛的距离存在着一些约束关系:1.有ML组(u, v, w)的约束关系,表示牛[u]和牛[v]之间的距离必须 <= w.2.有MD组(u, v, w)的约束关系,表示牛[u]和牛[v]之间的距离必须 >= w.问如果这n头无法排成队伍,则输出-1,如果牛[1]和牛[n]的距离可以无限远,则输出-2,否则则输出牛[1]和牛[n]之间的最

差分约束系统小结

百科是这样说的:如果一个系统由n个变量和m个约束条件组成,其中每个约束条件形如xj-xi<=bk(i,j∈[1,n],k∈[1,m]),则称其为差分约束系统.亦即,差分约束系统是求解关于一组变量的特殊不等式组的方法. 学习差分约束系统之前,必须掌握单源最短路径的算法(Bellman-ford.SPFA).习惯上用SPFA解差分约束的题目. 解题思想有两种: 假设j > i, 1.由xj - xi >=w得到xj >= xi + w,建立一条从xi->xj的边权为w的边.然后用

Burn the Linked Camp(bellman 差分约束系统)

Burn the Linked Camp Time Limit: 2 Seconds      Memory Limit: 65536 KB It is well known that, in the period of The Three Empires, Liu Bei, the emperor of the Shu Empire, was defeated by Lu Xun, a general of the Wu Empire. The defeat was due to Liu Be