| 12
 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;
 }
 
 
 |