现在的位置: 首页 > 综合 > 正文

POJ 3189 Steady Cow Assignment

2012年02月06日 ⁄ 综合 ⁄ 共 1110字 ⁄ 字号 评论关闭

POJ_3189

    一开始题意各种理解错,首先输入的那个矩阵第i行第j列的值表示的是奶牛i会第j个中意的牛棚,最后求的range就相当于j的range,至于range是变化的范围,比如j在1、2变化,那么range就应该是2,也就是MAX-MIN+1。

    因此我们可以枚举range的下界和上届,然后用二分图多重匹配判断是否有解,当然用网络流判断也可以,不过好像比较慢。在枚举range的时候可以做到O(N),比如现在range是[x,y],如果当前无解那么就扩大上届令y=y+1,如果有解就缩小下届令x=x+1。

#include<stdio.h>
#include<string.h>
#include<algorithm>
#define MAXN 1010
#define MAXB 30
#define INF 0x3f3f3f3f
int N, B, yM[MAXB][MAXN], visy[MAXB], num[MAXB], limit[MAXB];
int g[MAXN][MAXB], LOW, HIGH;
void init()
{
    int i, j, k;
    for(i = 0; i < N; i ++)
        for(j = 0; j < B; j ++)
            scanf("%d", &g[i][j]), -- g[i][j];
    for(i = 0; i < B; i ++) scanf("%d", &limit[i]);
}
int searchpath(int cur)
{
    int i, y, j;
    for(i = LOW; i <= HIGH; i ++)
        if(!visy[g[cur][i]])
        {
            y = g[cur][i], visy[y] = 1;
            if(num[y] < limit[y])
            {
                yM[y][num[y] ++] = cur;    
                return 1;
            }
            for(j = 0; j < num[y]; j ++)
                if(searchpath(yM[y][j]))
                {
                    yM[y][j] = cur;
                    return 1;    
                }
        }
    return 0;
}
int match()
{
    int i;
    memset(num, 0, sizeof(num[0]) * B);
    for(i = 0; i < N; i ++)
    {
        memset(visy, 0, sizeof(visy[0]) * B);
        if(!searchpath(i)) return 0;
    }
    return 1;
}
void solve()
{
    int ans = INF;
    LOW = HIGH = 0;
    while(HIGH < B)
    {
        if(!match())
            ++ HIGH;
        else
            ans = std::min(ans, HIGH - LOW + 1), ++ LOW;
    }
    printf("%d\n", ans);
}
int main()
{
    while(scanf("%d%d", &N, &B) == 2)
    {
        init();
        solve();    
    }
    return 0;    
}

抱歉!评论已关闭.