1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107
|
using namespace std; const int maxn = 55; const int inf = -0x3f3f3f3f; int shop[maxn][maxn],sup[maxn][maxn],cost[maxn][maxn][maxn];
int n,m,k,cntA,cntB,delta; int belongA[maxn*3],belongB[maxn*3]; int w[maxn*3][maxn*3],la[maxn*3],lb[maxn*3],match[maxn*3]; bool va[maxn*3],vb[maxn*3];
void read() { for (int i=1; i<=n; ++i) for (int j=1; j<=k; ++j) scanf("%d",&shop[i][j]); for (int i=1; i<=m; ++i) for (int j=1; j<=k; ++j) scanf("%d",&sup[i][j]); for (int t=1; t<=k; ++t) for (int i=1; i<=n; ++i) for (int j=1; j<=m; ++j) scanf("%d",&cost[t][i][j]); }
int dfs(int u) { va[u] = 1; for (int i=1; i<=cntB; ++i) { if (!vb[i]) { if (la[u]+lb[i] - w[u][i] == 0) { vb[i] = 1; if (!match[i] || dfs(match[i])) { match[i] = u; return 1; } } else delta = min(delta,la[u]+lb[i]-w[u][i]); } } return 0; }
int KM () { for (int i=0; i<maxn*3; ++i) la[i] = -inf; memset(lb,0,sizeof lb); for (int i=1; i<=cntA; ++i) for (int j=1; j<=cntB; ++j) la[i] = max(la[i],w[i][j]); memset(match,0,sizeof match); for (int i=1; i<=cntA; ++i) { while (1) { memset(va,0,sizeof va); memset(vb,0,sizeof vb); delta = inf; if (dfs(i)) break; for (int i=1; i<=cntB; ++i) { if (va[i]) la[i] -= delta; if (vb[i]) lb[i] += delta; } } } int ans = 0; for (int i=1; i<=cntB; ++i) if (match[i]) ans += w[match[i]][i]; return ans; } int main() { freopen("1.in","r",stdin); while (scanf("%d%d%d",&n,&m,&k) != EOF && (n+m+k)) { read(); // 判断仓库的货物是否足够 bool flag = 1; for (int i=1; i<=k; ++i) { int need =0, have = 0; for (int j=1; j<=n; ++j) need += shop[j][i]; for (int j=1; j<=m; ++j) have += sup[j][i]; if (need > have) { flag = 0; printf("-1\n"); break; } } if (!flag) continue; int ans = 0; // KM分别处理每个货物 for (int t=1; t<=k; ++t) { cntA = cntB = 0; for (int i=1; i<=n; ++i) for (int j=1; j<=shop[i][t]; ++j) belongA[++cntA] = i; //给同一种货物的所有货物标号顺便 标记属于哪个店家 for (int i=1; i<=m; ++i) for (int j=1; j<=sup[i][t]; ++j) belongB[++cntB] = i; //存储点的货物属于哪个仓库,并且给每个相同货物标记号码 for (int i=1; i<=cntA; ++i) for (int j=1; j<=cntB; ++j) w[i][j] = -cost[t][belongA[i]][belongB[j]]; ans += KM(); } printf("%d\n",-ans); } return 0; }
|