CODE[VS] 2171 Tyvj P1035 棋盘覆盖

15 篇文章 0 订阅
9 篇文章 0 订阅

题目描述 Description

给出一张n*n(n<=100)的国际象棋棋盘,其中被删除了一些点,问可以使用多少1*2的多米诺骨牌进行掩盖。

输入描述 Input Description

第一行为n,m(表示有m个删除的格子)
第二行到m+1行为x,y,分别表示删除格子所在的位置
x为第x行
y为第y列

输出描述 Output Description

一个数,即最大覆盖格数

样例输入 Sample Input

8 0

样例输出 Sample Output

32

数据范围及提示 Data Size & Hint

经典问题

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

二分图匹配~

覆盖一个点相当于是把两个点放入两个不同子集中,直接套匈牙利算法~

如果用bool变量记录连接状态会MLE,所以我用了邻接表来记,用匈牙利算法前先预处理出连接状态,输出结果的时候除以二就可以了~


#include<cstdio>
#include<cstring>
#include<vector>
using namespace std;

int n,m,x,y,ans,c[101][101][2],val[3][5]={{0,0,0,0,0},{0,1,-1,0,0},{0,0,0,1,-1}};
bool b[101][101];
vector<int> a[101][101][2];

bool dfs(int u,int v)
{
	for(int i=0;i<a[u][v][0].size();i++)
	  if(!b[a[u][v][0][i]][a[u][v][1][i]])
	  {
	  	b[a[u][v][0][i]][a[u][v][1][i]]=1;
	  	if(!c[a[u][v][0][i]][a[u][v][1][i]][0] || dfs(c[a[u][v][0][i]][a[u][v][1][i]][0],c[a[u][v][0][i]][a[u][v][1][i]][1]))
	  	{
	  		c[a[u][v][0][i]][a[u][v][1][i]][0]=u;
	  		c[a[u][v][0][i]][a[u][v][1][i]][1]=v;
	  		return 1;
		}
	  }
	return 0;
}

int main()
{
	scanf("%d%d",&n,&m);
	for(int i=1;i<=m;i++) scanf("%d%d",&x,&y),b[x][y]=1;
	for(int i=1;i<=n;i++)
	  for(int j=1;j<=n;j++)
	    if(!b[i][j])
	    {
	    	for(int k=1;k<=4;k++)
	    	  if((i+val[1][k])>0 && (i+val[1][k])<=n && (j+val[2][k])>0 && (j+val[2][k])<=n && !b[i+val[1][k]][j+val[2][k]])
	    	  {
	    	  	a[i][j][0].push_back(i+val[1][k]);a[i][j][1].push_back(j+val[2][k]);
			  }
		}
	for(int i=1;i<=n;i++)
	  for(int j=1;j<=n;j++)
	  {
		memset(b,0,sizeof(b));
		if(dfs(i,j)) ans++;
	  }
	printf("%d\n",ans/2);
	return 0;
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值