题意:给出m个机器,现在要生产n个糖果,每个糖果可以在任意一个机器上生产,每个糖果的生产时间是一个区间[s,t],必须在[s,t)时间内开始生产,否则就无法生产了,生产的费用为(p-s)*k,p是开始生产的时间。对于一个机器j来说,从最开始没生产的状态转化为生产第i个糖果的状态需要花费C[i][j]的时间并花费D[i][j],对于一个在生产第i个糖果的机器来说,将其转化为生产第j个糖果需要花费E[i][j]的时间并花费F[i][j],现在要生产这n个糖果并让所有花费最小。
思路:一看就是个网络流的问题,不过建图还是有些麻烦的,首先将n个糖果拆成两个点,如果左边第i个糖果生产完,可以生产右边的j,那么连边,流量为1,费用为转换的费用+生产费用,S向左边的点连边,流量为1,费用为0,右边的点向T连边,流量为1,费用为0。添加点u,从S向u连边,流量为m,费用为0,再从u向m个点连边,流量为1,费用为0,接下来m个点代表最开始这个机器生产哪个糖果,如果可以最开始生产某个糖果,向右边的对应点连边,流量为1,费用为转换费用+生产费用。这样就能保证最后的费用流就是答案。
代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<map>
#include<queue>
#include<stack>
#include<cmath>
#include<vector>
#include<bitset>
#define inf 0x3f3f3f3f
#define Inf 0x3FFFFFFFFFFFFFFFLL
#define eps 1e-6
#define pi acos(-1.0)
using namespace std;
typedef long long ll;
const int maxn=300+10;
const int maxm=100000+10;
struct Edge
{
int to,cap,cost,next;
Edge(int to=0,int cap=0,int cost=0,int next=0):to(to),cap(cap),cost(cost),next(next){}
}edges[maxm<<1];
int head[maxn],d[maxn],a[maxn],p[maxn],nEdge,S,T;
bool inq[maxn];
int st[maxn],tt[maxn],C[maxn][maxn],D[maxn][maxn],E[maxn][maxn],F[maxn][maxn];
void AddEdges(int from,int to,int cap,int cost)
{
edges[++nEdge]=Edge(to,cap,cost,head[from]);
head[from]=nEdge;
edges[++nEdge]=Edge(from,0,-cost,head[to]);
head[to]=nEdge;
}
int spfa(int &flow,int &cost)
{
memset(inq,0,sizeof(inq));
memset(d,0x3f,sizeof(d));
queue<int>q;
q.push(S);
d[S]=0;a[0]=inf;
while(!q.empty())
{
int u=q.front();q.pop();
inq[u]=false;
for(int k=head[u];k!=-1;k=edges[k].next)
{
Edge &e=edges[k];
if(d[e.to]>d[u]+e.cost&&e.cap)
{
d[e.to]=d[u]+e.cost;
a[e.to]=min(a[u],e.cap);
p[e.to]=k;
if(!inq[e.to]) {inq[e.to]=true;q.push(e.to);}
}
}
}
if(d[T]==inf) return false;
flow+=a[T];
cost+=a[T]*d[T];
int u=T;
while(u!=S)
{
edges[p[u]].cap-=a[T];
edges[p[u]^1].cap+=a[T];
u=edges[p[u]^1].to;
}
return true;
}
int main()
{
//freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
int n,m,K;
while(~scanf("%d%d%d",&n,&m,&K))
{
if(n==0&&m==0&&K==0) break;
memset(head,0xff,sizeof(head));
nEdge=-1;
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]);
S=0,T=n*2+m+2;
for(int i=1;i<=n;++i)
{
AddEdges(S,i,1,0);
AddEdges(i+n,T,1,0);
for(int j=1;j<=n;++j)
{
if(i!=j&&tt[i]+E[i][j]<tt[j])
{
int c=max(tt[i]+E[i][j],st[j])-st[j];
c*=K;
AddEdges(i,n+j,1,c+F[i][j]);
}
}
}
AddEdges(S,n*2+m+1,m,0);
for(int i=1;i<=m;++i)
{
AddEdges(n*2+m+1,n*2+i,1,0);
for(int j=1;j<=n;++j)
{
if(C[j][i]<tt[j])
{
int c=max(C[j][i],st[j])-st[j];
c*=K;
AddEdges(n*2+i,j+n,1,c+D[j][i]);
}
}
}
int flow=0,cost=0;
while(spfa(flow,cost));
if(flow!=n) printf("-1\n");
else printf("%d\n",cost);
}
return 0;
}