SD第九届省赛B题 Bullet

本文介绍了一种解决GGO游戏中玩家Shino如何在限定条件下获取最大经验值的问题。通过使用二分法和匹配算法,文章详细阐述了如何在n×n的地图中,玩家在每列和每行最多只能击杀一个怪物的前提下,实现经验值的最大化。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Bullet

Time Limit: 1000 ms Memory Limit: 65536 KiB
Problem Description

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 \times nn×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.

Input

The first line contains an integer nn. (n<=500)
Then n lines follow. In each line there are n integers, and AijAij represents the experience of the monster at grid (i,j)(i,j). If Aij=0Aij=0, there is no monster at grid (i,j)(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 10^9

Output

One integer, the value of max experience.

Sample Input
2
2 0
1 8
Sample Output
2
Hint
 
Source
“浪潮杯”山东省第九届ACM大学生程序设计竞赛(感谢山东财经大学)
 
求获得最大匹配 用到的经验值的最小值最大化
就是一个水二分 + 匹配
记得只对w不为0的i和j建边
先求出最大匹配max_flow 
然后二分最小值就好了
我的最小值最大化板子翻车了。。。。。。
我用的Dinic写的  匈牙利就好了
 
#include <iostream>
#include <cstdio>
#include <sstream>
#include <cstring>
#include <map>
#include <cctype>
#include <set>
#include <vector>
#include <stack>
#include <queue>
#include <algorithm>
#include <cmath>
#include <bitset>
#define rap(i, a, n) for(int i=a; i<=n; i++)
#define rep(i, a, n) for(int i=a; i<n; i++)
#define lap(i, a, n) for(int i=n; i>=a; i--)
#define lep(i, a, n) for(int i=n; i>a; i--)
#define rd(a) scanf("%d", &a)
#define rlld(a) scanf("%lld", &a)
#define rc(a) scanf("%c", &a)
#define rs(a) scanf("%s", a)
#define rb(a) scanf("%lf", &a)
#define rf(a) scanf("%f", &a)
#define pd(a) printf("%d\n", a)
#define plld(a) printf("%lld\n", a)
#define pc(a) printf("%c\n", a)
#define ps(a) printf("%s\n", a)
#define MOD 2018
#define LL long long
#define ULL unsigned long long
#define Pair pair<int, int>
#define mem(a, b) memset(a, b, sizeof(a))
#define _  ios_base::sync_with_stdio(0),cin.tie(0)
//freopen("1.txt", "r", stdin);
using namespace std;
const int maxn = 1e6 + 10, INF = 0x7fffffff;
int n, s, t;
int head[maxn], cur[maxn], vis[maxn], d[maxn], cnt, nex[maxn << 1];

struct node
{
    int u, v, c;
}Node[maxn << 1];

void add_(int u, int v, int c)
{
    Node[cnt].u = u;
    Node[cnt].v = v;
    Node[cnt].c = c;
    nex[cnt] = head[u];
    head[u] = cnt++;
}

void add(int u, int v, int c)
{
    add_(u, v, c);
    add_(v, u, 0);
}

bool bfs()
{
    queue<int> Q;
    mem(d, 0);
    Q.push(s);
    d[s] = 1;
    while(!Q.empty())
    {
        int u = Q.front(); Q.pop();
        for(int i = head[u]; i != -1; i = nex[i])
        {
            int v = Node[i].v;
            if(!d[v] && Node[i].c > 0)
            {
                d[v] = d[u] + 1;
                Q.push(v);
                if(v == t) return 1;
            }
        }
    }
    return d[t] != 0;
}

int dfs(int u, int cap)
{
    int ret = 0;
    if(u == t || cap == 0)
        return cap;
    for(int &i = cur[u]; i != -1; i = nex[i])
    {
        int v = Node[i].v;
        if(d[v] == d[u] + 1 && Node[i].c > 0)
        {
            int V = dfs(v, min(cap, Node[i].c));
            Node[i].c -= V;
            Node[i ^ 1].c += V;
            ret += V;
            cap -= V;
            if(cap == 0) break;
        }
    }
    if(cap > 0) d[u] = -1;
    return ret;
}

int Dinic()
{
    int ans = 0;
    while(bfs())
    {
        memcpy(cur, head, sizeof head);
        ans += dfs(s, INF);
    }
    return ans;
}

int w[550][550];

void build(int m)
{
    mem(head, -1);
    cnt = 0;
    for(int i = 1; i <= n; i++)
    {
        add(s, i, 1);
        add(n + i, t, 1);
        for(int j = 1; j <= n; j++)
            if(w[i][j] >= m)
                add(i, n + j, 1);
    }


}


int main()
{
    while(cin >> n)
    {
        int sum = 0;
        mem(head, -1);
        cnt = 0;
        s = 0, t = maxn - 1;
        int l = 1e9, r = 0;
        for(int i = 1; i <= n; i++)
        {
            add(s, i, 1);
            add(n + i, t, 1);
            for(int j = 1; j <= n; j++)
            {
                rd(w[i][j]);
                if(w[i][j])
                    add(i, n + j, 1);
                l = min(l, w[i][j]);
                r = max(r, w[i][j]);
            }
        }
        int max_flow = Dinic();

        while(l < r)
        {
            int m = (l + r + 1) / 2;
            build(m);
            if(Dinic() < max_flow) r = m - 1;
            else l = m;
        }
        cout << r << endl;
    }

    return 0;
}
View Code

 

 

转载于:https://www.cnblogs.com/WTSRUVF/p/10715685.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值