ゲーム(ハンガリー)

説明

2016年、嘉源の妹はバブルホールと呼ばれるゲームに恋をしました。

簡単に言えば、このゲームは、マップ上にいくつかの爆弾を置いて、敵を攻撃できるかどうか、または敵の爆弾を回避できるかどうかを確認することです。ゲームをプレイする過程で、Xiao Hは質問を考えました。マップが与えられたとき、2つの爆弾が互いに吹き飛ばされないように、このマップに爆弾をいくつ配置できるかということです。爆弾は、爆弾が配置されている行と列の範囲に到達できます。爆弾の力は、硬い岩ではなく、柔らかい岩に浸透できます。

n×mのグリッドマップが与えられた場合:ここで、*はオープンスペースを表し、爆弾の力が浸透し、爆弾をオープンスペースに配置できます。xはソフトロックの略で、爆弾の力は浸透でき、爆弾はここに置くことができません。#ハードロックを表します。爆弾の力が伝わらないため、ここに爆弾を置くことはできません。例:1×4グリッドマップ* xx *の場合、このマップに配置できる爆弾は1つだけです。別の1×4グリッドマップ* x#*が与えられると、このマップは最大2つの爆弾を配置できます。

Xiao Hは、n×mのグリッドマップを任意に与え、最大でいくつの爆弾を配置できるかを尋ねます。

入力フォーマット

最初の行に2つの正の整数n、mを入力します。ここで、nはマップの行数を表し、mはマップの列数を表します。
次に、グリッドマップを表すn行m列の文字を入力します。*数はn×mを超えません

出力フォーマット

配置できる爆弾の最大数を示す整数aを出力します

サンプル
入力
4 4
#***
*#**
**#*
xxxは番号の
出力
5
データ範囲とプロンプト
1≤n、m≤50

解決

石に関係なく、通常の行と列の場合
、行がセットに分割され、列がセットに分割されることは明らかです。
当然、行と列は交差しません。
ハンガリーは、次の2部グラフを実行できます最大の一致。

ソフトロックが追加されたので、
ランクを通過できるパワーの制限は変更されていませんが、ソフトロックは爆弾を置くことができません。

次に、チェス盤の特定の行と特定の列を分割することに相当する最も特殊な硬い岩を考えます。
現時点では、同じ行の同じ列に爆弾があり、硬い石で区切られ
ている可能性があります。ハードロック制限を直接追加し、行と列の番号を強制的に変更します(行と列の数を増やします)。次に
、ハンガリーの最大一致を実行します。

コード

#include <cstdio>
#include <vector>
#include <cstring>
using namespace std;
#define maxn 55
vector < int > G[maxn * maxn];
int n, m;
char chess[maxn][maxn];
int row[maxn][maxn], col[maxn][maxn]; 
bool vis[maxn * maxn];
int match[maxn * maxn];

bool find( int u ) {
    
    	
	for( int i = 0;i < G[u].size();i ++ ) {
    
    
		int v = G[u][i];
		if( vis[v] ) continue;
		vis[v] = 1;
		if( ! match[v] || find( match[v] ) ) {
    
    
			match[v] = u;
			return 1;
		}
	}
	return 0;
}

int main() {
    
    
	scanf( "%d %d", &n, &m );
	for( int i = 1;i <= n;i ++ )
		scanf( "%s", chess[i] + 1 );
	int num = 0;
	for( int i = 1;i <= n;i ++ )
		for( int j = 1;j <= m;j ++ ) {
    
    
			if( chess[i][j] == '#' ) continue;
			if( j == 1 || chess[i][j - 1] == '#' ) num ++;
			row[i][j] = num;
		}
	for( int j = 1;j <= m;j ++ )
		for( int i = 1;i <= n;i ++ ) {
    
    
			if( chess[i][j] == '#' ) continue;
			if( i == 1 || chess[i - 1][j] == '#' ) num ++;
			col[i][j] = num;
		}
	for( int i = 1;i <= n;i ++ )
		for( int j = 1;j <= m;j ++ )
			if( chess[i][j] == '*' )
				G[row[i][j]].push_back( col[i][j] );
	int ans = 0;
	for( int i = 1;i <= num;i ++ ) {
    
    
		memset( vis, 0, sizeof( vis ) );
		if( find( i ) ) ans ++;
	}
	printf( "%d\n", ans );
	return 0;
}

おすすめ

転載: blog.csdn.net/Emm_Titan/article/details/113687361