Candy Factory
Total Submission(s): 382 Accepted Submission(s): 185
There are N candies need to be produced. These candies are also numbered from 1 to N. For each candy i , it can be produced in any machine j. It also has a producing time(s i,t i) , meaning that candy i must start producing at time s i and will finish at t i. Otherwise if the start time is p i(s i < p i < t i) then candy will still finish at t i but need additional K*(p i - s i) cost. The candy can’t be produced if p i is greater than or equal to t i. Of course one machine can only produce at most one candy at a time and can’t stop once start producing.
On the other hand, at time 0 all the machines are in their initial state and need to be “set up” or changed before starting producing. To set up Machine j from its initial state to the state which is suitable for producing candiy i, the time required is C ij and cost is D ij. To change a machine from the state suitable for candy i 1 into the state suitable for candy i 2, time required is E i1i2 and cost is F i1i2.
As the manager of the factory you have to make a plan to produce all the N candies. While the sum of producing cost should be minimized.
For each case, the first line contains three integers N(1<=N<=100), M(1<=M<=100), K(1<=K<=100) . The meaning is described above.
Then N lines follow, each line contains 2 integers s i and t i(0 <= s i < t i <100000).
Then N lines follow, each line contains M integers, the j-th integer of the i-th line indicating C ij(1<=C ij<=100000) .
Then N lines follow, each line contains M integers, the j-th integer of the i-th line indicating D ij(1<=D ij<=100000) .
Then N lines follow, each line contains N integers, the i 2-th integer of the i 1-th line indicating E i1i2(1<=E i1j2<=100000) .
Then N lines follow, each line contains N integers, the i 2-th integer of the i 1-th line indicating F i1i2(1 <= F i1j2<=100000) .
Since the same candy will only be produced once, E ii and F ii are meaningless and will always be -1.
The input ends by N=0 M=0 K=0. Cases are separated with a blank line.
3 2 1 4 7 2 4 8 9 4 4 3 3 3 3 2 8 12 3 14 6 -1 1 1 1 -1 1 1 1 -1 -1 5 5 5 -1 5 5 5 -1 1 1 2 1 5 5 5 -1 -1 0 0 0
11 -1HintFor the first example, the answer can be achieved in the following way:In the picture, S i represents setting up time for candy i, A i represents changing time for candy i and P i represents producing time for candy i . So the total cost includes: setting up machine 1 for candy 1, costs 2 setting up machine 2 for candy 2, costs 3 changing state from candy 2 to candy 3, costs 5 late start of candy 2, costs 1
题意:M 台机器生产 N 颗糖果,有如下规则
(1)生产每颗糖果的时间为[si, ti],如果从pi(si < pi < ti)开始,那么产生费用 K * (pi - si);
(2)每台机器开始使用时需要一个启动时间 C[i][j] 以及启动费用 D[i][j],代表 i 糖果触发 j 机器启动,需要时间C[i][j],花费D[i][j];
(3)当一台机器生产完 i 糖果后 可继续生产 j 糖果,期间需要一个缓冲时间为 E[i][j],花费 F[i][j];
现在问生产完所有糖果所花费的最小费用,若不能全部生产则输出 -1。
分析:最小费用流。直接按照规则建图,由于糖果与糖果之间可以连边,所以可以把糖果拆点,保证一颗糖果只生产一次。对于糖果 i 与糖果 j 之间的转换,连边 j -> i' 表示 j 可在 i 糖果之后生产。
建图:
(1)加入超级源点s(0),s 连向每颗糖果 i,连边 s -> i,容量为1,费用为0;
(2)加入超级汇点t(2 * N + M + 1),每台机器 i 连向 t,连边 i + 2 * N -> t,容量为1,费用为0;每颗糖果 j 连向 t,连边 N + j -> t,容量为1,费用为0;
(3)对于第二条规则,对于糖果 i、机器 j (C[i][j] < t[i]),如果 C[i][j] > s[i],那么 cost = D[i][j] + K * (C[i][j] - st[i]),否则 cost = D[i][j],连边 i -> 2 * N + j,容量为1,费用为cost;
(4)对于第三条规则,对于糖果 i、糖果 j (t[i] + E[i][j] < t[j]),如果 t[i] + E[i][j] > s[j],那么 cost = F[i][j] + K * (t[i] + E[i][j] - t[j]),否则 cost = F[i][j],连边 j -> N + i,容量为1,费用为cost。
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4780
代码清单:
/*******************************************************************************
*** problem ID : HDU_4780.cpp
*** create time : Sat Oct 31 13:48:49 2015
*** author name : nndxy
*** author blog : http://blog.csdn.net/jhgkjhg_ugtdk77
*** author motto: never loose enthusiasm for life, life is to keep on fighting!
*******************************************************************************/
#include <map>
#include <set>
#include <cmath>
#include <queue>
#include <stack>
#include <ctime>
#include <vector>
#include <cctype>
#include <string>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
using namespace std;
#define end() return 0
typedef long long ll;
typedef unsigned int uint;
typedef unsigned long long ull;
const int maxn = 300 + 5;
const int INF = 0x7f7f7f7f;
struct Edge{
int from, to, cap, flow, cost;
Edge(int u, int v, int c, int f, int w) : from(u), to(v), cap(c), flow(f), cost(w) {}
};
struct MCMF{
int n, m, flow, cost;
vector <Edge> edge; //边数的两倍
vector <int> G[maxn]; //邻接表,G[i][j]表示i的第j条边在e数组中的序号
int inq[maxn]; //是否在队列
int d[maxn]; //Bellman-Ford
int p[maxn]; //上一条弧
int a[maxn]; //可改进量
void init(int n){
this -> n = n;
for(int i = 0; i <=n ; i++) G[i].clear();
edge.clear();
}
void addEdge(int from, int to, int cap, int cost){
edge.push_back(Edge(from, to, cap, 0, cost));
edge.push_back(Edge(to, from, 0, 0, -cost));
m = edge.size();
G[from].push_back(m-2);
G[to].push_back(m-1);
}
bool BellmanFord(int s, int t, int& flow, int& cost){
memset(d, INF, sizeof(d));
memset(inq, 0, sizeof(inq));
d[s] = 0; inq[s] = 1; p[s] = 0; a[s] = INF;
queue <int> q;
q.push(s);
while(!q.empty()){
int u = q.front(); q.pop();
inq[u] = 0;
for(int i = 0; i < G[u].size(); i++){
Edge& e = edge[G[u][i]];
if(e.cap > e.flow && d[e.to] > d[u] + e.cost){
d[e.to] = d[u] + e.cost;
p[e.to] = G[u][i];
a[e.to] = min(a[u], e.cap - e.flow);
if(!inq[e.to]){
q.push(e.to);
inq[e.to] = 1;
}
}
}
}
if(d[t] == INF) return false;
flow += a[t];
cost += d[t] * a[t];
for(int u = t; u != s; u = edge[p[u]].from){
edge[p[u]].flow += a[t];
edge[p[u]^1].flow -= a[t];
}
return true;
}
//需要保证初始网络中没有负权圈
void MincostMaxflow(int s, int t){
this -> flow = 0, this -> cost = 0;
while(BellmanFord(s, t, flow, cost));
}
};
int N, M, K;
int st[maxn], tt[maxn];
int C[maxn][maxn], D[maxn][maxn];
int E[maxn][maxn], F[maxn][maxn];
MCMF mcmf;
int tail;
void input(){
for(int i = 1; i <= N ; i++){
scanf("%d%d", &st[i], &tt[i]);
}
for(int i = 1; i <= N; i++){
for(int j = 1; j <= M; j++){
scanf("%d", &C[i][j]);
}
}
for(int i = 1; i <= N; i++){
for(int j = 1; j <= M; j++){
scanf("%d", &D[i][j]);
}
}
for(int i = 1; i <= N; i++){
for(int j = 1; j <= N; j++){
scanf("%d", &E[i][j]);
}
}
for(int i = 1; i <= N; i++){
for(int j = 1; j <= N; j++){
scanf("%d", &F[i][j]);
}
}
}
void createGraph(){
tail = N + N + M + 1;
mcmf.init(tail + 1);
for(int i = 1; i <= N; i++){
mcmf.addEdge(0, i, 1, 0);
mcmf.addEdge(N + i, tail, 1, 0);
}
for(int i = 1; i <= M; i++){
mcmf.addEdge(2 * N + i, tail, 1, 0);
}
for(int i = 1; i <= N; i++){
for(int j = 1; j <= M; j++){
if(C[i][j] >= tt[i]) continue;
int cost = D[i][j];
if(C[i][j] > st[i]) cost += K * (C[i][j] - st[i]);
mcmf.addEdge(i, 2 * N + j, 1, cost);
}
}
for(int i = 1; i <= N; i++){
for(int j = 1; j <= N; j++){
if(i == j) continue;
if(tt[i] + E[i][j] >= tt[j]) continue;
int cost = F[i][j];
if(tt[i] + E[i][j] > st[j]) cost += K *(tt[i] + E[i][j] - st[j]);
mcmf.addEdge(j, N + i, 1, cost);
}
}
}
void solve(){
createGraph();
mcmf.MincostMaxflow(0, tail);
if(mcmf.flow < N) printf("-1\n");
else printf("%d\n", mcmf.cost);
}
int main(){
while(scanf("%d%d%d", &N, &M, &K) != EOF && N && M && K){
input();
solve();
} end();
}