ACM: 图论题 poj 1275 差分约束题

来源:互联网 发布:java酒店管理系统程序 编辑:程序博客网 时间:2024/05/18 17:55
CashierEmployment
 
Description
A supermarket in Tehran is open24 hours a day every day and needs a number of cashiers to fit itsneed. The supermarket manager has hired you to help him, solve hisproblem. The problem is that the supermarket needs different numberof cashiers at different times of each day (for example, a fewcashiers after midnight, and many in the afternoon) to provide goodservice to its customers, and he wants to hire the least number ofcashiers for this job.

The manager has provided you with the least number of cashiersneeded for every one-hour slot of the day. This data is given asR(0), R(1), ..., R(23): R(0) represents the least number ofcashiers needed from midnight to 1:00 A.M., R(1) shows this numberfor duration of 1:00 A.M. to 2:00 A.M., and so on. Note that thesenumbers are the same every day. There are N qualified applicantsfor this job. Each applicant i works non-stop once each 24 hours ina shift of exactly 8 hours starting from a specified hour, say ti(0 <= ti <= 23), exactly from thestart of the hour mentioned. That is, if the ith applicant ishired, he/she will work starting from ti o'clock sharp for 8 hours.Cashiers do not replace one another and work exactly as scheduled,and there are enough cash registers and counters for those who arehired.

You are to write a program to read the R(i) 's for i=0..23 and ti's for i=1..N that are all, non-negative integer numbers andcompute the least number of cashiers needed to be employed to meetthe mentioned constraints. Note that there can be more cashiersthan the least number needed for a specific slot.

Input

The first line of input is thenumber of test cases for this problem (at most 20). Each test casestarts with 24 integer numbers representing the R(0), R(1), ...,R(23) in one line (R(i) can be at most 1000). Then there is N,number of applicants in another line (0 <= N<= 1000), after which come N lines each containingone ti (0 <= ti <= 23). There are noblank lines between test cases.

Output

For each test case, the outputshould be written in one line, which is the least number ofcashiers needed.
If there is no solution for the test case, you should write NoSolution for that case.

Sample Input

1
1 0 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1
5
0
23
22
1
10

Sample Output

1

 

题意: 现在一家24小时的超市要雇佣出纳员, 每个小时段的出纳员需求都不一样, 已知24小时内的需求,

     并且给出n个出纳员的开始工作时间, 每个出纳员工作8个小时, 问怎么雇佣最少的出纳员满足需求

 

解题思路:

    1. 设: r[i]表示每小时需要的出纳员的数目. t[i]表示每小时应征的申请则数目.(1<=i<=24)

        设s[i]表示1~i时刻雇佣出纳员的总数.s[i]-s[i-1]表示在i时刻雇佣的出纳员数目.

    2. 题目给出的约束条件有: (sum需要雇佣出纳员的数量)

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

                           s[i-1]-s[i] >= -t[i];

                           s[24]-s[0] >= sum;

                           s[i]-s[j] >=r[i]  当i>j时  (i=(j+9)% 25)

                                      >= r[i]-sum 当i<j时

     3.在这些不等式中, 唯一我们不知道的是sum, 也是我们需要求解, 采用二分枚举的方法找出结果.

       建图s[a]-s[b] >= c 可以从点b向点a连一条边权值为c,这样问题就变成从0到24求最短路问题.

       当图中不存在负环且s[24] == sum, 则枚举的sum是一个可行解.

     4.最短路+负环判断用spfa算法即可.

 

代码:

#include <cstdio>
#include <iostream>
#include <cstring>
#include <queue>
using namespace std;
#define MAX 26
const int INF = (1<<28);

struct node
{
 int v;
 int w;
 int next;
}edges[MAX*MAX];

int n, num;
int t[MAX], r[MAX], first[MAX];
int dist[MAX], size[MAX];
int up, low;
bool vis[MAX];

inline void add(int u, int v, int w)
{
 edges[num].v = v;
 edges[num].w = w;
 edges[num].next = first[u];
 first[u] = num++;
}

void readGraph()
{
 int i, temp;
 memset(t, 0, sizeof(t));
 for(i = 1; i <= 24; ++i)
  scanf("%d",&r[i]);
 scanf("%d", &n);
 for(i = 1; i <= n; ++i)
 {
  scanf("%d",&temp);
  t[temp+1]++;
 }
}

bool spfa(int sum)
{
 int i;
 for(i = 1; i <= 24; ++i)
 {
  dist[i] = -INF;
  size[i] = 0;
  vis[i] = false;
 }

 queue qu;
 qu.push(0);
 dist[0] = 0;
 vis[0] = true;
 size[0] = 1;

 while( !qu.empty() )
 {
  int u = qu.front();
  qu.pop();
  vis[u] = false;
  if( size[u] > 24) return false;
  for(int e = first[u]; e != -1;e = edges[e].next)
  {
   if( dist[edges[e].v ] < dist[u]+edges[e].w )
   {
    dist[edges[e].v ] = dist[u]+edges[e].w;
    if(!vis[edges[e].v] )
    {
     vis[edges[e].v]= true;
     size[edges[e].v ]++;
     qu.push(edges[e].v);
    }
   }
  }
 }

 return dist[24] == sum;
}

bool solve(int sum)
{
 int i, j;
 memset(first, -1, sizeof(first));
 num = 0;
 for(i = 1; i <= 24; ++i)
 {
  j = i-8;
  if(j < 0) j =(i-9+25)%;
  if(i > j) add(j,i, r[i]);
  else add(j, i, r[i]-sum);

  add(i-1, i, 0);
  add(i, i-1, -t[i]);
 }
 add(0, 24, sum);

 return spfa(sum);
}

int binarySearch()
{
 int result = -1;
 int left = 0, right = n, mid;
 while(left <= right)
 {
  mid = (left+right)/2;
  if( solve(mid) )
  {
   right =mid-1;
   result =mid;
  }
  else
   left =mid+1;
 }
 return result;
}

int main()
{
// freopen("input.txt", "r", stdin);
 int caseNum;
 scanf("%d", &caseNum);
 while( caseNum-- )
 {
  readGraph();
  int result =binarySearch();
  if(result == -1)
   printf("NoSolution\n");
  else
   printf("%d\n",result);
 }
 return 0;
}

 

0 0
原创粉丝点击