CODE[VS]1028 花店橱窗布置

题目:http://codevs.cn/problem/1028/
思路:KM算法求解
题解:

/* 1028 花店橱窗布置 */
#include <stdio.h>

#define MAXN 101
#define max(X,Y) ((X>Y)?X:Y)
#define min(X,Y) ((X<Y)?X:Y)
#define INF 2147483647
int F, V;                       /* 花束数,花瓶数 */
int aesthetics[MAXN][MAXN];     /* 花束-花瓶美学值对应表 */
int linky[MAXN], visx[MAXN], visy[MAXN], lack;
int lx[MAXN] = {0}, ly[MAXN] = {0};
int maxans;                     /* 最大美学值 */

/* 匈牙利算法 */
int find(int x)
{
    int y;
    int t;
    /* 标记花束x已访问 */
    visx[x] = 1;
    for(y = 1; y <= V; y++)
    {
        /* 如果花瓶y已使用,继续下一次循环 */
        if(1 == visy[y])
        {
            continue;
        }
        /* 计算是否匹配 */
        t = lx[x] + ly[y] - aesthetics[x][y];
        if(0 == t)
        {
            visy[y] = 1;
            if(0 == linky[y] || 1 == find(linky[y]))
            {
                linky[y] = x;
                return 1;
            }
        }
        else
        {
            lack = min(lack, t);
        }
    }
    return 0;
}

/* KM算法 */
void km()
{
    int fi, vi, i;
    /* 初始化链接关系 */
    for(vi = 1; vi <= V; vi++)
    {
        linky[vi] = 0;
    }
    /* 初始化花束顶标值 */
    for(fi = 1; fi <= F; fi++)
    {
        for(vi = 1; vi <= V; vi++)
        {
            lx[fi] = max(lx[fi], aesthetics[fi][vi]);
        }
    }
    /* 初始化花瓶顶标值 */
    for(vi = 1; vi <= V; vi++)
    {
        ly[vi] = 0;
    }
    /* 求完备匹配 */
    for(fi = 1;  fi <= F; fi++)
    {
        for(;;)
        {
            /* 清零访问标记 */
            for(i = 1; i <= V; i++)
            {
                visx[i] = 0;
                visy[i] = 0;
            }
            lack = INF;
            if(1 == find(fi))
            {
                break;
            }
            /* 修改已访问点顶标值 */
            for(i = 1; i <= V; i++)
            {
                if(1 == visx[i])
                {
                    lx[i] = lx[i] - lack;
                }
                if(1 == visy[i])
                {
                    ly[i] = ly[i] + lack;
                }
            }
        }
    }
    /* 测试 - 打印顶标值及对应表 */
    /*
    printf("花瓶-花束对应表:\n");
    for(vi = 1; vi <= V; vi++)
    {
        if(0 != linky[vi])
        {
            printf("V[%2d](%2d) -> F[%2d](%2d)\n", vi, ly[vi], linky[vi], lx[linky[vi]]);
        }
    }
    */
    /******************/
}

/* 主函数入口 */
int main()
{
    int fi, vi;         /* 索引值 */
    /* 打开数据文件 */
    FILE *fp;
    if(NULL == (fp = fopen("data.txt", "r")))
    {
        return 1;
    }
    /***************/

    /* 获取花束数,花瓶数 */
    fscanf(fp, "%d %d", &F, &V);
    /* 获取对应美学值 */
    for(fi = 1; fi <= F; fi++)
    {
        for(vi = 1; vi <= V; vi++)
        {
            fscanf(fp, "%d", &aesthetics[fi][vi]);
        }
    }
    km();
    maxans = 0;
    for(vi = 1; vi <= V; vi++)
    {
        maxans = maxans + aesthetics[linky[vi]][vi];
    }
    /* 打印结果 */
    printf("%d", maxans);
    /* 关闭数据文件 */
    fclose(fp);
    /****************/
    return 0;
}

猜你喜欢

转载自blog.csdn.net/QQ604666459/article/details/78320118
今日推荐