POJ3686 The Windy's

POJ3686 The Windy's
Time Limit: 5000MS Memory Limit: 65536K
Total Submissions: 2536 Accepted: 1084

Description

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 previous one. The switch does not cost any time.

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笔订单, 订单i在j厂完成所需时间为c[i][j], 要求一笔订单只能在一个厂完成, 一个厂不能同时做一笔以上订单, 求一个分配方案, 使得每个任务的平均完成时间最小.
先来吐糟一下:{首先,我看了题目,发现出不来样例啊!怎么回事,我怎么看不懂样例!然后叫ZYC帮我看,原来是我题意理解错误。然后,我开始建图,纠结,异常纠结,我想呢,我怎么判断第i个订单在第j个车间加工时,第j个车间之前已经加工了什么订单呢?怎么也确定不了,于是,傻掉了。再然后,我上网搜了解题报告,报告是一大堆,讲来讲去说这道题目是好题,建图很巧妙。我懂的啊,图论题目,最难的就是建图嘛。可以,网上的报告,我怎么也就不明白呢,不知道在讲什么,我靠,纠结。再然后,陪XNJ出去买杯子,哦,似乎想通了这道题怎么做,好开心啊,开始写。再然后,我发现怎么也找不出错误,而且貌似是初始化有问题,毛蛋,我把所有数组都清零了还是有问题,这我怎么就这么背捏,一个n写成m了!再然后,我飞速改完,交上去,WA了,发现数组可能要开大一点,再交WA了,也许是某个常数写得太小了改大一点,再交还是WA了,我心都毛了,什么狗蛋啊,和标程对了一下,发现还有一个数组开小了,再交AC。这个AC,我满肚子火啊,太纠结了,唉唉唉!!!}//吐糟结束
说一下思路,的确像网上众人所说,这道题目的建图异常奇妙。首先碰到的就像我一开始的那个问题,确定不了第i个订单在第j个车间加工时,第j个车间之前已经加工了什么订单。然而换一种想法就想的通了。我们这样想:如果第i个订单在第j个车间加工完后,这个车间又加工了k个订单,那这k个订单每个都需要加上Zij的时间,这个绑定很是特别,需要用心体会,上面那个链接讲得不错,不再赘述。
#include <stdio.h>

#include <string.h>

#include <vector>

#include <algorithm>

#define N 55

#define INF 0x3f3f3f3f

using namespace std;



int n,m,lack;

int tu[N][N],gra[N][N*N];

int mat[N*N],visx[N],visy[N*N];

int lx[N],ly[N*N];



int dfs(int x)

{

    visx[x]=1;

    for(int y=1;y<=n*m;y++)

    {

        if(visy[y])continue;

        int t=lx[x]+ly[y]-gra[x][y];

        if(t==0)

        {

            visy[y]=1;

            if(!mat[y]||dfs(mat[y]))

            {

                mat[y]=x;

                return 1;

            }

        }

        else lack=min(lack,t);

    }

    return 0;

}



void re(void)

{

    scanf("%d%d",&n,&m);

    memset(ly,0,sizeof(ly));

    for(int i=1;i<=n;i++)

    {

        lx[i]=-INF;

        for(int j=1;j<=m;j++)

        {

            scanf("%d",&tu[i][j]);

            for(int k=1;k<=n;k++)

            {

                gra[i][(j-1)*n+k]=-tu[i][j]*k;

                lx[i]=max(lx[i],-tu[i][j]*k);

            }



        }

    }

}



void run(void)

{

    memset(mat,0,sizeof(mat));

    for(int x=1;x<=n;x++)

    {

        memset(visx,0,sizeof(visx));

        memset(visy,0,sizeof(visy));

        lack=INF;

        while(!dfs(x))

        {

            for(int i=1;i<=n;i++)

                if(visx[i])

                    visx[i]=0,lx[i]-=lack;

            for(int i=1;i<=n*m;i++)

                if(visy[i])

                    visy[i]=0,ly[i]+=lack;

            lack=INF;

        }

    }

    int ans=0;

    for(int i=1;i<=n*m;i++)

        if(mat[i])

            ans-=gra[mat[i]][i];

    printf("%.6lf\n",1.0*ans/n);

}



int main()

{

    int ncase;

    scanf("%d",&ncase);

    while(ncase--)

    {

        re();

        run();

    }

    return 0;

}

  

你可能感兴趣的:(poj)