poj 1275 差分约束系统
2016-09-08 19:48
337 查看
题目:http://poj.org/problem?id=1275
题意:
Tehran的一家每天24小时营业的超市,需要一批出纳员来满足它的需要。超市经理雇佣你来帮他解决他的问题——超市在每天的不同时段需要不同数目的出纳员(例如:午夜时只需一小批,而下午则需要很多)来为顾客提供优质服务。他希望雇佣最少数目的出纳员。 经理已经提供你一天的每一小时需要出纳员的最少数量——R(0), R(1), …, R(23)。R(0)表示从午夜到上午1:00需要出纳员的最少数目,R(1)表示上午1:00到2:00之间需要的,等等。每一天,这些数据都是相同的。有N人申请这项工作,每个申请者I在没24小时中,从一个特定的时刻开始连续工作恰好8小时,定义tI (0 <= tI <= 23)为上面提到的开始时刻。也就是说,如果第I个申请者被录取,他(她)将从tI 时刻开始连续工作8小时。 你将编写一个程序,输入R(I)(I = 0..23)和tI (I = 1..N),它们都是非负整数,计算为满足上述限制需要雇佣的最少出纳员数目。在每一时刻可以有比对应的R(I)更多的出纳员在工作。
输入
输入文件的第一行为测试点个数(<= 20)。每组测试数据的第一行为24个整数表示R(0),R(1),…, R(23)(R(I)<= 1000)。接下来一行是N,表示申请者数目(0 <= N <= 1000),接下来每行包含一个整数tI (0 <= tI <= 23)。两组测试数据之间没有空行。
输出
对于每个测试点,输出只有一行,包含一个整数,表示需要出纳员的最少数目。如果无解,你应当输出“No Solution”。
分析:
设num[ i ]为i时刻能够开始工作的人数,x[ i ]为实际雇佣的人数,那么x[ I ]<=num[ I ]。 设r[ i ]为i时刻至少需要工作的人数,于是有如下关系:
x[ I-7 ]+x[ I-6 ]+…+x[ I ]>=r[ I ]
设s[ I ]=x[ 1 ]+x[ 2 ]…+x[ I ],
得到
0<=s[ I ]-s[ I-1 ]<=num[ I ], 0<=I<=23
s[ I ]-s[ I-8 ]>=r[ I ], 8<=I<=23
s[ 23 ]+s[ I ]-s[ I+16 ]>=r[ I ], 0<=I<=7
整理下:
s[ I ]-s[ I-1 ]>=0 (0<=I<=23)
s[ I-1 ]-s[ I ]>=-num[ I ] (0<=I<=23)
s[ I ]-s[ I-8 ]>=r[ I ] (8<=I<=23)
s[ I ]-s[ I+16 ]>=r[ I ]-s[ 23 ] (0<=I<= 7)
这题自己想了半天没想出来,是看了冯威的论文上的思路~~
代码:
题意:
Tehran的一家每天24小时营业的超市,需要一批出纳员来满足它的需要。超市经理雇佣你来帮他解决他的问题——超市在每天的不同时段需要不同数目的出纳员(例如:午夜时只需一小批,而下午则需要很多)来为顾客提供优质服务。他希望雇佣最少数目的出纳员。 经理已经提供你一天的每一小时需要出纳员的最少数量——R(0), R(1), …, R(23)。R(0)表示从午夜到上午1:00需要出纳员的最少数目,R(1)表示上午1:00到2:00之间需要的,等等。每一天,这些数据都是相同的。有N人申请这项工作,每个申请者I在没24小时中,从一个特定的时刻开始连续工作恰好8小时,定义tI (0 <= tI <= 23)为上面提到的开始时刻。也就是说,如果第I个申请者被录取,他(她)将从tI 时刻开始连续工作8小时。 你将编写一个程序,输入R(I)(I = 0..23)和tI (I = 1..N),它们都是非负整数,计算为满足上述限制需要雇佣的最少出纳员数目。在每一时刻可以有比对应的R(I)更多的出纳员在工作。
输入
输入文件的第一行为测试点个数(<= 20)。每组测试数据的第一行为24个整数表示R(0),R(1),…, R(23)(R(I)<= 1000)。接下来一行是N,表示申请者数目(0 <= N <= 1000),接下来每行包含一个整数tI (0 <= tI <= 23)。两组测试数据之间没有空行。
输出
对于每个测试点,输出只有一行,包含一个整数,表示需要出纳员的最少数目。如果无解,你应当输出“No Solution”。
分析:
设num[ i ]为i时刻能够开始工作的人数,x[ i ]为实际雇佣的人数,那么x[ I ]<=num[ I ]。 设r[ i ]为i时刻至少需要工作的人数,于是有如下关系:
x[ I-7 ]+x[ I-6 ]+…+x[ I ]>=r[ I ]
设s[ I ]=x[ 1 ]+x[ 2 ]…+x[ I ],
得到
0<=s[ I ]-s[ I-1 ]<=num[ I ], 0<=I<=23
s[ I ]-s[ I-8 ]>=r[ I ], 8<=I<=23
s[ 23 ]+s[ I ]-s[ I+16 ]>=r[ I ], 0<=I<=7
整理下:
s[ I ]-s[ I-1 ]>=0 (0<=I<=23)
s[ I-1 ]-s[ I ]>=-num[ I ] (0<=I<=23)
s[ I ]-s[ I-8 ]>=r[ I ] (8<=I<=23)
s[ I ]-s[ I+16 ]>=r[ I ]-s[ 23 ] (0<=I<= 7)
这题自己想了半天没想出来,是看了冯威的论文上的思路~~
代码:
#include <cstdio> #include <iostream> #include <vector> #include <algorithm> #include <cstring> #include <string> #include <map> #include <cmath> #include <queue> #include <set> using namespace std; typedef long long ll; const int INF = 1e9 + 9; const int mod = 1000007; const int N = 100000 + 9; struct Edge { int v, w, next; } edge[3 * N]; int head , d , vis , num , r , tot , n, Max, Min, cnt; void addedge (int u, int v, int w) { edge[cnt].v = v; edge[cnt].w = w; edge[cnt].next = head[u]; head[u] = cnt++; } int spfa (int ans) { for (int i = 0; i <= 25; i++) { d[i] = -INF; vis[i] = 0; tot[i] = 0; } queue<int>q; d[0]=0; q.push (0); while (!q.empty() ) { int u = q.front(); q.pop(); vis[u] = 0; for (int i = head[u]; ~i; i = edge[i].next) { if (d[edge[i].v] < d[u] + edge[i].w) { d[edge[i].v] = d[u] + edge[i].w; if (!vis[edge[i].v]) { q.push (edge[i].v); vis[edge[i].v] = 1; if (++tot[edge[i].v] > 24) return 0; } } } } if (d[24] == ans) return 1; return 0; } void build (int ans) { cnt = 0; memset (head, -1, sizeof (head) ); addedge (0, 24, ans); for (int i = 1; i <= 24; i++) { addedge (i - 1, i, 0); addedge (i, i - 1, -num[i]); } for (int i = 1; i <= 8; i++) addedge (i + 16, i, r[i] - ans); for (int i = 9; i <= 24; i++) addedge (i - 8, i, r[i]); } int main() { //freopen ("f.txt", "r", stdin); int u, v, w; int T; scanf ("%d", &T); while (T--) { bool flag = 0; for (int i = 1; i <= 24; i++) { scanf ("%d", &r[i]); num[i] = 0; } scanf ("%d", &n); int t; for (int i = 0; i < n; i++) { scanf ("%d", &t); num[t + 1]++; } for (int i = 0; i <= n; i++) { build (i); if (spfa (i) ) { flag = 1; printf ("%d\n", i); break; } } if (!flag) puts ("No Solution"); } return 0; }
相关文章推荐
- OpenCv形态学操作和漫水填充
- 371 Sum of Two Integers
- 关于Android Studio中的org.gradle.jvmargs=-Xmx1024m问题
- Time Series Prediction:时间序列预测
- php学习网站
- 为何更好的产品不一定更成功
- 123
- POJ 3259 Wormholes(SPFA判负权回路)
- My Git Flow
- Java类与对象(二)
- bzoj3261 最大异或和(可持久化字典树)
- 多种方式垂直水平居中
- Java 求全排列的两种方式
- 关于memset的注意事项
- Java类与对象(一)
- linux查看日志常用命令
- Android----给Ta惊喜,带音乐的动态相册
- JAVA基础6.45——继承概述(1)
- linux系统性能监控常用命令
- POJ 2449 A*k短路