The Windy's is a world famous toy factory that owns M top-class workshop to make toys. This year the manager receives N orders for toys. The manager knows that every order will take different amount of hours in different workshops. More precisely, the i-th order will take Zij hours if the toys are making in the j-th workshop. Moreover, each order's work must be wholly completed in the same workshop. And a workshop can not switch to another order until it has finished the
The manager wants to minimize the average of the finishing time of the N orders. Can you help him?
Input
The first line of input is the number of test case. The first line of each test case contains two integers, N and M (1 ≤ N,M ≤ 50).
The next N lines each contain M integers, describing the matrix Zij (1 ≤ Zij ≤ 100,000) There is a blank line before each test case.
Output
For each test case output the answer on a single line. The result should be rounded to six decimal places.
Sample Input
3
3 4
100 100 100 1
99 99 99 1
98 98 98 1
3 4
1 100 100 100
99 1 99 99
98 98 1 98
3 4
1 100 100 100
1 99 99 99
98 1 98 98
Sample Output
2.000000 1.000000 1.333333 题意: 玩具公司现在有M台机器, N个任务, 要你求出完成每个任务的平均时间最少.
解题思路:
1. 一看题目的时候一头雾水, 看别人的题解: 二分图最佳匹配问题. 想起KM算法.
2. 现在将二分图分成X,Y两部分. X部有N个点, Y部有N*M个点
3. 将每台机器拆成N个点,使得Y部有N*M个点,
(1)第J个机器的第P个点代表: 使用J机器进行倒数第P次加工.
(2)假设N个订单执行的时间分别是t1,t2,t3,...,tn. 执行n个订单的执行时间是:
t1*n + t2*(n-1) + t3*(n-2) + ... + tn-1*2 + tn
(3)将每个机器J拆成N个点,第k个点表示倒数第k个订单在此机器上完成.
连边的权值为: graph[i][j]*k
代码:
#include <cstdio>
#include <iostream>
#include <cstring>
using namespace std;
#define MAX 105
#define _clr(x) memset(x,0xff,sizeof(int)*n)
const int INF = (1<<29);
int graph[MAX][MAX];
int mat[MAX][MAX*MAX];
int match1[MAX*MAX], match2[MAX*MAX];
int n, m;
int kuhn_munkras(int m,int n,int mat[][MAX*MAX],int *match1,int *match2)
{
int s[MAX*MAX], t[MAX*MAX], l1[MAX*MAX], l2[MAX*MAX];
int p, q, i, j, k;
int ret = 0;
for(i = 0; i < m; ++i)
{
l1[i] = -INF;
for(j = 0; j < n; ++j)
{
l1[i] = mat[i][j] > l1[i] ? mat[i][j] : l1[i];
}
}
for(i = 0; i < n; ++i) l2[i] = 0;
_clr(match1), _clr(match2);
for(i = 0; i < m; ++i)
{
for(_clr(t),s[p=q=0] = i; p <= q && match1[i] < 0; ++p)
{
for(k = s[p], j = 0; j < n && match1[i] < 0; ++j)
{
if(l1[k]+l2[j] == mat[k][j] && t[j] < 0)
{
s[++q] = match2[j];
t[j] = k;
if(s[q] < 0)
{
for(p = j; p >= 0; j = p)
{
match2[j] = k = t[j];
p = match1[k];
match1[k] = j;
}
}
}
}
}
if(match1[i] < 0)
{
for(i--, p = INF, k = 0; k <= q; ++k)
for(j = 0; j < n; ++j)
if(t[j] < 0 && l1[s[k]] + l2[j] - mat[s[k]][j] < p)
p = l1[s[k]] + l2[j] - mat[s[k]][j];
for(j = 0; j < n; l2[j] += t[j] < 0 ? 0 : p, j++);
for(k = 0; k <= q; l1[s[k++]] -= p);
}
}
for(i = 0; i < m; ++i)
ret += mat[i][match1[i]];
return ret;
}
int main()
{
//freopen("input.txt","r",stdin);
int i, j;
int caseNum;
scanf("%d",&caseNum);
while(caseNum--)
{
scanf("%d %d",&n,&m);
for(i = 0; i < n; ++i)
{
for(j = 0; j < m; ++j)
scanf("%d",&graph[i][j]);
}
for(i = 0; i < n; ++i)
{
for(j = 0; j < m; ++j)
{
for(int k = 0; k < n; ++k)
{
mat[i][j*n+k] = -graph[i][j]*(k+1);
}
}
}
int result = -kuhn_munkras(n,n*m,mat,match1,match2);
printf("%.6lf\n",(double)result/n);
}
return 0;
}