hdu 1281 最大匹配数求解类八皇后问题

题意:n*m的格子只有k个位置可以放置棋子,给出这k个位置。同一行或同一列的棋子之间会冲突。若这k个位置中某个位置变成了不可放棋子的位置,可放棋子数减少了,那么这样的位置称为重要点。求在摆放棋子最多的情况下问有多少个重要点。

题解:最大匹配数

1.棋子放在一个位置等价于一行匹配一列,就转化为了最大匹配数问题。这就算出了棋子摆放的最多数目。

2.枚举k个位置,每次枚举减少一个位置,计算最多能摆放几个棋子,若小于最多摆放数目,则该位置是重要点。

3.used[j]=i表示第i行第j列存在一个棋子,used数组是理解这道题的关键。

4.套用匈牙利模板即可。

#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<vector>
#include<math.h>
using namespace std ;
int n , m , k ;
int x[10005] , y[10005] ;
int map1[105][105] ;
int used[105] ;
bool vis[105] ;
bool find(int u) 
{
  int i , j ;
  for(i = 1 ; i <= m ; i ++)
  {
    if(map1[u][i] && !vis[i])
	{
		vis[i] = 1 ;
		if(used[i] == 0 || find(used[i]))
		{
			used[i] = u ;
			return 1 ;
		}
	}	
  }	
  return 0 ;
}
int Match()
{
	int i , j , k ;
	int ans = 0 ;
	memset(used , 0 , sizeof(used)) ;
	//used[j] = i 表示第i行第j列已摆放棋子 
	//理解这个数组就理解了这种类八皇后问题 
	for(i = 1 ; i <= n ; i ++)
	{
		memset(vis , 0 , sizeof(vis)) ;
		if(find(i))
		   ans ++ ;
	}
	return ans ; 
}
int main()
{
  int i , j , k ;
  int ans , temp ;
  int cnt = 0 ;
  int num ;
  while(scanf("%d%d%d" , &n , &m , &k) != EOF)
  {
  	memset(map1 , 0 , sizeof(map1)) ;
  	for(i = 1 ; i <= k ; i ++)
    {
    	scanf("%d%d" , &x[i] , &y[i]) ;
    	map1[x[i]][y[i]] = 1 ;
	}
	ans = Match() ;
	num = 0 ;
	for(i = 1 ; i <= k; i ++) 
	{
	  map1[x[i]][y[i]] = 0 ;
	  //该点若不能放棋子,那么总棋子数是否会减少。 
	  //若会减少,则该点是重要点。 
	  temp = Match() ;
	  if(temp < ans) 
	     num ++ ;
	  map1[x[i]][y[i]] = 1 ;
	}
	printf("Board %d have %d important blanks for %d chessmen.\n" , ++cnt , num , ans) ;
  }
} 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值