现场赛这题就看了一眼就再没多想了,被别的题卡住的时候就更没心思想了,比较可惜。
模型一眼就是费用流,主要是题意的理解和构图方式。
首先机器的区别只在于一开始做每个糖果的花费和时间不同,除此之外没有任何区别。
每个糖果生产完毕的时间也是确定的(Ti),所以某机器生产完一个糖果又生产另一个糖果的花费也是确定的。
所以时间的意义只在于计算费用而已啦……
构图就比较清晰了:
从源点到每个机器连边,流量1费用0。
每个糖果拆成两个点,分为入点和出点,从入点到出点连上界下界都是1费用为0的边,在把每个糖果的出点同汇点连边,流量1费用0。
对于每个机器和每个糖果的入点,计算花费连流量为1的边。
每个糖果之间也如此连边。
跑最小费用流,当下界没满足(maxflow<n)时输出-1即可。
code:
int n , m , K;
int S , T;
#define Maxn 100
int SS[Maxn] , TT[Maxn];
int C[Maxn][Maxn] , D[Maxn][Maxn] , E[Maxn][Maxn] , F[Maxn][Maxn];
void work()
{
int i , j , x , y;
S = n + m + n , T = S + 1 , s = T + 1 , t = s + 1;
for (i = 0 ; i < n ; ++ i)
scanf("%d%d",&SS[i] , &TT[i]);
for (i = 0 ; i < n ; ++ i)
for (j = 0 ; j < m ; ++ j)
scanf("%d",&C[j][i]);
for (i = 0 ; i < n ; ++ i)
for (j = 0 ; j < m ; ++ j)
scanf("%d",&D[j][i]);
for (i = 0 ; i < n ; ++ i)
for (j = 0 ; j < n ; ++ j)
scanf("%d",&E[i][j]);
for (i = 0 ; i < n ; ++ i)
for (j = 0 ; j < n ; ++ j)
scanf("%d",&F[i][j]);
memset(pre , -1 , sizeof(pre)) , mcnt = 0;
for (i = 0 ; i < n ; ++ i)
{
addarc(s , i << 1 | 1 , 1 , 0);
addarc(i << 1 , t , 1 , 0);
addarc(i << 1 | 1 , T , 1 , 0);
}
for (i = n + n ; i < n + n + m ; ++ i)
addarc(S , i , 1 , 0);
for (i = 0 ; i < m ; ++ i)
for (j = 0 ; j < n ; ++ j)
{
x = i + n + n;
if (C[i][j] <= SS[j])
addarc(x , j << 1 , 1 , D[i][j]);
else if (C[i][j] < TT[j])
addarc(x , j << 1 , 1 , D[i][j] + K * (C[i][j] - SS[j]));
}
for (i = 0 ; i < n; ++ i)
for (j = 0 ; j < n ; ++ j) if (i != j)
{
x = TT[i] + E[i][j];
if (x <= SS[j])
addarc(i << 1 | 1 , j << 1 , 1 , F[i][j]);
else if (x < TT[j])
addarc(i << 1 | 1 , j << 1 , 1 , F[i][j] + K * (x - SS[j]));
}
addarc(T , S , 1 << 30 , 0);
Mincostflow();
if (maxflow != n)
puts("-1");
else printf("%d\n" , ans);
}