zoukankan      html  css  js  c++  java
  • 51nod 1368:黑白棋 二分图最大匹配

    题目来源: TopCoder
    基准时间限制:1 秒 空间限制:131072 KB 分值: 160 难度:6级算法题
     收藏
     取消关注
    有一个N*M的棋盘(1<=N,M<=50),棋盘上有一些黑色的和白色的棋子。定义棋盘上两个位置相邻是指这两个格子存在公共边。已知棋盘中的白色棋子都不与其他白色棋子相邻。现在玩家可以向棋盘中空格的位置上放入一些黑色棋子,当一个白色棋子相邻的格子都被黑色的棋子占据的时候,这颗白色的棋子会被移出棋盘,而它原来的位置将变为空格,值得注意的是一些边界上的白色棋子其相邻的格子可能不足4个,但是只要这些格子里都是黑色,它就得移除。玩家的目的是放一些黑色的棋子后使棋盘上的空格最大化。求最优策略下棋盘上最多能有多少个空格?(空格指没有棋子的格子。)
    Input
    多组测试数据,第一行一个整数T,表示测试数据数量,1<=T<=5
    每组测试数据有相同的结构构成:
    每组数据的第一行有两个整数N,M,表示棋盘的大小,其中1<=N,M<=50.
    之后有一个N*M的字符矩阵S,表示棋盘初始状态,其中S[i][j]='.'表示(i,j)格式空的,S[i][j]='x'表示这个格子中有一个黑棋,S[i][j]='o'表示这个格子中有一个白棋。保证任意两颗白棋不相邻。
    Output
    每组数据一行输出,即棋盘上最多可能出现多少个空格.
    Input示例
    3
    3 3
    o.o
    .o.
    o.o
    3 3
    ...
    .o.
    ...
    5 5
    xxxxx
    xxoxx
    xo.ox
    xxoxx
    xxxxx
    Output示例
    5
    8
    4

    二分图,将相邻的白棋和空格建边,求两者的最大匹配。最终结果是白棋的数量+空格的数量-匹配的数量。

    代码:

    #include <iostream>
    #include <algorithm>
    #include <cmath>
    #include <vector>
    #include <string>
    #include <cstring>
    #include <map>
    #pragma warning(disable:4996)
    using namespace std;
    
    int n, m;
    int v1, v2;
    int link[2502];
    int visit[2502];
    char val[52][52];
    int grid[2502][2502];
    
    map<int, int>white;
    map<int, int>blank;
    
    bool bfs(int x)
    {
    	int i;
    	for (i = v2; i >= 1; i--)
    	{
    		if (grid[x][i] && visit[i] == 0)
    		{
    			visit[i] = 1;
    			if (link[i] == -1 || bfs(link[i]))
    			{
    				link[i] = x;
    				return true;
    			}
    		}
    	}
    	return false;
    }
    
    void Magyarors()
    {
    	int i, sum;
    	memset(link, -1, sizeof(link));
    
    	sum = 0;
    	for (i = v1; i >= 1; i--)
    	{
    		memset(visit, 0, sizeof(visit));
    		if (bfs(i))
    		{
    			sum++;
    		}
    	}
    	cout << v1+v2-sum << endl;
    }
    
    int main()
    {
    	//freopen("i.txt","r",stdin);
    	//freopen("o.txt","w",stdout);
    
    	int test, i, j, num_w, num_b, pos_w, pos_b;
    	cin >> test;
    
    	while (test--)
    	{
    		memset(grid, 0, sizeof(grid));
    		memset(val, 0, sizeof(val));
    		white.clear();
    		blank.clear();
    		num_w = 0;
    		num_b = 0;
    
    		cin >> n >> m;
    		for (i = 1; i <= n; i++)
    		{
    			cin >> val[i] + 1;
    			for (j = 1; j <= m; j++)
    			{
    				if (val[i][j] == 'o')
    				{
    					white[i*m + j] = ++num_w;
    				}
    				if (val[i][j] == '.')
    				{
    					blank[i*m + j] = ++num_b;
    				}
    			}
    		}
    		
    		v1 = num_w;
    		v2 = num_b;
    		
    		for (i = 1; i <= n; i++)
    		{
    			for (j = 1; j <= m; j++)
    			{
    				if (val[i][j] == 'o')
    				{
    					pos_w = white[i*m + j];
    					if (val[i - 1][j] == '.')
    					{
    						pos_b = blank[(i - 1)*m + j];
    						grid[pos_w][pos_b] = 1;
    					}
    					if (val[i + 1][j] == '.')
    					{
    						pos_b = blank[(i + 1)*m + j];
    						grid[pos_w][pos_b] = 1;
    					}
    					if (val[i][j + 1] == '.')
    					{
    						pos_b = blank[i*m + j + 1];
    						grid[pos_w][pos_b] = 1;
    					}
    					if (val[i][j - 1] == '.')
    					{
    						pos_b = blank[i*m + j - 1];
    						grid[pos_w][pos_b] = 1;
    					}
    				}
    			}
    		}
    
    		Magyarors();
    	}
    	//system("pause");
    	return 0;
    }
    



    版权声明:本文为博主原创文章,未经博主允许不得转载。

  • 相关阅读:
    chrome提供的功能
    运用Detours库hook API(原理是改写函数的头5个字节)
    markdown实现
    SQL知识整理一:触发器、存储过程、表变量、临时表
    SOCKET网络编程细节问题(4)
    C++内存中的封装、继承、多态(上)
    100个直接可以拿来用的JavaScript实用功能代码片段
    背包问题的动态规划算法
    项目Splash页面的开发与设计
    cocos2d-x 通过socket实现http下载及断点续传的实现
  • 原文地址:https://www.cnblogs.com/lightspeedsmallson/p/4928105.html
Copyright © 2011-2022 走看看