Bullet二分图 匈牙利+二分

A . Bullet
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×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 n(n≤500)
Then n lines follow. In each line there are n integers, and Aijrepresents the experience of the monster at grid(i,j). If Aij=0, there is no monster at grid(i,j).
Aij≤109
Output
One integer, the value of max experience.

Samples
Input 复制
2
2 0
1 8
Output
2

题意:
大概为n*n的矩阵 0代表没有怪兽

打怪兽需要注意 如果打了当前这个怪兽 那么这个怪兽所在的行和列其他怪兽都不能打了
所以 如果以行为基准的话 行和列进行二分图匹配 就可以得到最多可以打几个怪兽
但是他又让求在你打的这些怪兽中 最小经验值最大 意思就是 让最小值尽可能的大点
类似 极限 就是说如果 目前这个最小经验值已经最大了 如果再大的话 那么就不能打最多的怪兽了
所以这里利用二分最小经验值 小于最小经验值的置0 代表没有怪兽
然后重新进行 行和列的二分图匹配 得到新的打怪兽数量 如果数量和初始值一样 就说明当前最小经验值可以满足 那么l=mid 求再大点的最小经验值 否则 r=mid-1 使最小经验值再小点

然后代码

#include <map>
#include <stack>
#include <queue>
#include <vector>
#include <math.h>
#include <string>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <algorithm>
#include <time.h>
#include <set>
#include <list>
#include <iostream>

using namespace std;
//mapip;
//mapcy; 

typedef long long ll;
const int maxn=500+188;
const ll inf=1e11;
ll n,m,k,flag,cnt,sum;
/*
struct node{
	int x,y,w;
	operator <(node a){
		return w
int a[maxn][maxn];int G[maxn][maxn];
int from[maxn];
bool vis[maxn];// 二分图
bool match(int x){
	for(int i=1;i<=n;i++){
		if(!vis[i]&&a[x][i]){
			vis[i]=1;
			if(from[i]==-1||match(from[i])){
				from[i]=x;
				return 1;
			}
		}
	}
	return 0;
} 

int solve(){
	int tot=0;memset(from,-1,sizeof(from));
	for(int i=1;i<=n;i++){
		memset(vis,0,sizeof(vis));
		if(match(i)) tot++;
	}
	return tot;
}

bool check(int x){
	for(int i=1;i<=n;i++){
		for(int j=1;j<=n;j++){
			if(G[i][j]>=x) a[i][j]=G[i][j];
			else a[i][j]=0;
		}
	}
	int ans=solve();
	if(ans<sum) return 0;
	return 1;
}
int main(){
	cin>>n;int l=1000000000,r=-1;
	for(int i=1;i<=n;i++){
		for(int j=1;j<=n;j++){
			cin>>G[i][j];
			a[i][j]=G[i][j];
			l=min(l,a[i][j]); r=max(r,a[i][j]);
		}
	}
	sum=solve();
	while(l<r){
		int mid=(l+r+1)>>1;
		if(!check(mid)) r=mid-1;
		else l=mid;
	}
	cout<<l;
	return 0;
} 

你可能感兴趣的:(题目,数据结构,算法)