• Hdu 2255奔小康赚大钱


    奔小康赚大钱

    Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
    Total Submission(s): 9383    Accepted Submission(s): 4137

    Problem Description

    传说在遥远的地方有一个非常富裕的村落,有一天,村长决定进行制度改革:重新分配房子。
    这可是一件大事,关系到人民的住房问题啊。村里共有n间房间,刚好有n家老百姓,考虑到每家都要有房住(如果有老百姓没房子住的话,容易引起不安定因素),每家必须分配到一间房子且只能得到一间房子。
    另一方面,村长和另外的村领导希望得到最大的效益,这样村里的机构才会有钱.由于老百姓都比较富裕,他们都能对每一间房子在他们的经济范围内出一定的价格,比如有3间房子,一家老百姓可以对第一间出10万,对第2间出2万,对第3间出20万.(当然是在他们的经济范围内).现在这个问题就是村领导怎样分配房子才能使收入最大.(村民即使有钱购买一间房子但不一定能买到,要看村领导分配的).

    Input

    输入数据包含多组测试用例,每组数据的第一行输入n,表示房子的数量(也是老百姓家的数量),接下来有n行,每行n个数表示第i个村名对第j间房出的价格(n<=300)。

    Output

    请对每组数据输出最大的收入值,每组的输出占一行。

    Sample Input

    2

    100 10

    15 23

    Sample Output

    123

    #include <iostream>
    #include<cstring>
    #include<cstdio>
    #include<cmath>
    const int maxn = 301;
    const int INF = (1<<31)-1;
    int w[maxn][maxn];
    int lx[maxn],ly[maxn]; //顶标
    int linky[maxn];
    int visx[maxn],visy[maxn];
    int slack[maxn];
    int n;
    bool find(int x)
    {
        visx[x] = true;
        for(int y = 1; y <=n; y++)
        {
            if(visy[y])
                continue;
            int t = lx[x] + ly[y] - w[x][y];
            if(t==0)
            {
                visy[y] = true;
                if(linky[y]==-1 || find(linky[y]))
                {
                    linky[y] = x;
                    return true;        //找到增广轨            }
            }
            else if(slack[y] > t)
                slack[y] = t;
        }
        return false;                   //没有找到增广轨(说明顶点x没有对应的匹配,与完备匹配(相等子图的完备匹配)不符)}
    
    int KM()                //返回最优匹配的值{
        int i,j;
    
        memset(linky,-1,sizeof(linky));
        memset(ly,0,sizeof(ly));
        for(i = 1; i <=n; i++)
        {
            lx[i] = -INF;
             for(j = 1; j <=n; j++)
                if(w[i][j] > lx[i])
                    lx[i] = w[i][j];
        }
    
        for(int x = 1; x <=n; x++)
        {
            for(i = 1; i <=n; i++)
                slack[i] = INF;
            while(true)
            {
                memset(visx,0,sizeof(visx));
                memset(visy,0,sizeof(visy));
                if(find(x))                     //找到增广轨,退出                break;
                int d = INF;
                for(i = 1; i <=n; i++)          //没找到,对l做调整(这会增加相等子图的边),重新找            {
                    if(!visy[i] && d > slack[i])
                        d = slack[i];
                }
                for(i = 1; i <=n; i++)
                {
                    if(visx[i])
                        lx[i] -= d;
                }
                for(i = 1; i <=n; i++)
                {
                    if(visy[i])
                         ly[i] += d;
                    else
                        slack[i] -= d;
                }
            }
        }
        int result = 0;
        for(i = 1; i <=n; i++)
        if(linky[i]>-1)
            result += w[linky[i]][i];
        return result;
    }
    
    int main()
    {
        while(scanf("%d",&n)==1)
        {
            int cost;
            for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++)
            {
                scanf("%d",&cost);
                w[i][j]=cost;
            }
            printf("%d
    ",KM());
        }
        return 0;
    }
    

      

  • 相关阅读:
    在C#中运用SQLDMO备份和恢复SQL Server数据库(转)
    c#中分割字符串的几种方法
    MS SQL Server中的日期格式化大全
    IBM基于双机热备份配置
    C#实现Des加密和解密
    ASP.NET备份恢复SqlServer数据库
    WEB 打印的相关技术分析
    通过身份证号码取得生日的一段代码(支持18位和15位身份证)
    C#的四种排序算法
    .net下读写配置文件app.config方法
  • 原文地址:https://www.cnblogs.com/zhangliu/p/7063208.html
Copyright © 2020-2023  润新知