浪潮杯第九届山东acm程序设计赛B题 Bullet

B.Bullet

链接:https://www.nowcoder.com/acm/contest/123/B
来源:牛客网

题目描述

In GGO, a world dominated by gun and steel, players are fighting for the honor of being the strongest gunmen. Player Shino is a sniper, and her aimed shot kills one monster at a time. Now she is in an n*n map, and there are monsters in some grids. Each monster has an experience. As a master, however, Shino has a strange self-restrain. She would kill at most one monster in a column, and also at most one in a row. Now she wants to know how to get max experience, under the premise of killing as many monsters as possible.

输入描述:

The first line contains an integer n.
n<=500
Then n lines follow. In each line there are n

integers, and Aij represents the experience of the monster at grid (i,j).
 If Aij=0, there is no monster at grid (i,j).
The experience is the minimal experience of all the monster which are killed.
It guaranteed that the maximum of the experience of the monster is not larger than 109

输出描述:

One integer, the value of max experience.

示例1

输入

复制

2
2 0
1 8

输出

复制

2

题解:

在GGO,一个以枪支和钢铁为主导的世界,球员们正在争取成为最强大的枪手。玩家Shino是一个狙击手,她的目标射击一次杀死一个怪物。现在她在n * n地图中,并且在某些网格中有怪物。每个怪物都有经验。然而,作为一个大师,诗乃有一种奇怪的自我约束。她最多会杀死一列中的一个怪物,最多也会杀死一行中的一个怪物。现在,她希望知道如何在杀死尽可能多的怪物的前提下获得最大的体验。

思路:

二分(最小最大)+二分匹配

1.杀死怪兽的数量尽可能大

2.使所杀死的全部怪物中的最小经验值最大化

二分匹配学习:https://blog.csdn.net/dark_scope/article/details/8880547

由题意得,使所射杀怪物中的最小经验值最大,最小最大问题,把消灭的怪兽的数量作为一个衡量的标准,对此二分图求出最大匹配ans。那么ans为最多能消灭的怪物数量。然后二分枚举经验值k,对于所有矩阵内值w[i][j]>=k的,按照上面一样重新建图并求出最大匹配值。如果求出的值等于ans,那么经验值k是合法的。因此求出最优的k值。

#include<iostream>
#include<cstdio>
#include<vector>
#include<cstring>
using namespace std;
const int maxn=550;
int n;
int from[maxn],w[maxn][maxn],ans,vis[maxn];
vector<int> g[maxn];
bool Find(int u)//行和列是否能匹配上
{
    for(int i=0;i<g[u].size();i++)
    {
        int v=g[u][i];
        if(!vis[v])
        {
            vis[v]=1;
            if(from[v]==-1|| Find(from[v]))
            {
                from[v]=u;
                return true;
            }
        }
    }
    return false;
}
int match()//求出最大能射死怪兽的数量
{
    int ret=0;
    memset(from,-1,sizeof(from));
    for(int i=0;i<n;i++)
    {
        memset(vis,0,sizeof(vis));
        if(Find(i)  ) ret++;
    }
    return ret;
}
bool check(int k)
{
    for(int i=0;i<n;i++)
        g[i].clear();
    for(int i=0;i<n;i++)
        for(int j=0;j<n;j++)
        if(w[i][j]>=k)
            g[i].push_back(j);
    return match()==ans;
}
int main()
{
    while(~scanf("%d",&n))
    {
        for(int i=0;i<n;i++)
            g[i].clear();
        for(int i=0;i<n;i++)
            for(int j=0;j<n;j++)
            scanf("%d",&w[i][j]);
        for(int i=0;i<n;i++)
            for(int j=0;j<n;j++)
        {
            if(w[i][j])
            {
                g[i].push_back(j);
            }
        }
        ans=match();
        int L=0,R=1e9;
        while(L<R)//二分枚举
        {
            int mid=(L+R+1)>>1;
            if(check(mid))
                L=mid;
            else
                R=mid-1;
        }
        printf("%d\n",L);
    }
    return 0;
}
 

猜你喜欢

转载自blog.csdn.net/lijunyan5/article/details/83036549