zoukankan      html  css  js  c++  java
  • {POJ}{4000}{National Treasures}{二分匹配}

    思路:观察宝物周围的keypoints与宝物位置的距离是奇数,也就转化成为染色问题,将图进行染色,黑色与白色之间构成二分图,求最小边覆盖即可。一道经典的染色转化问题。

    #include <iostream>
    #include <string>
    #include <cstring>
    #include <cstdio>
    #include <algorithm>
    #include <memory>
    #include <cmath>
    #include <bitset>
    #include <queue>
    #include <vector>
    #include <stack>
    using namespace std;
    
    const int MAXN = 2800;
    const int INF = (1<<30);
    
    #define CLR(x,y) memset(x,y,sizeof(x))
    #define MIN(m,v) (m)<(v)?(m):(v)
    #define MAX(m,v) (m)>(v)?(m):(v)
    #define ABS(x) ((x)>0?(x):-(x))
    #define rep(i,x,y) for(i=x;i<y;++i)
    
    int dir[12][2]={{-1,-2},{-2,-1},{-2,1},{-1,2},
    	{1,2},{2,1},{2,-1},{1,-2},
    	{-1,0},{0,1},{1,0},{0,-1}};
    int r,c,ind,ans;
    int g[MAXN][MAXN];
    int tt;
    typedef struct{
    	int v,next;
    }Edge;
    Edge edge[MAXN*MAXN];
    int net[MAXN];
    int pre[MAXN];
    bool vt[MAXN];
    
    bool _check(const int& x, const int& y )
    {
    	if( x < 0 || x >= r || y < 0 || y >= c)
    		return false;
    	return true;
    }
    void add_edge(const int& u , const int& v)
    {
    	edge[ind].v = v;
    	edge[ind].next = net[u];
    	net[u] = ind;
    	++ind;
    }
    bool dfs(const int& u)
    {
    	int i,v;
    	for( i = net[u]; i != -1; i = edge[i].next){
    		v = edge[i].v;
    		if( !vt[v] ){
    			vt[v] = true;
    			if( pre[v] == -1 || dfs(pre[v])){
    				pre[v] = u;
    				return true;
    			}
    		}
    	}
    	return false;
    }
    void init()
    {
    	CLR(net,-1);
    	CLR(pre,-1);
    	CLR(vt,0);
    	ind = 0;
    	return ;
    }
    void make_graph()
    {
    	int i,j,tmp,u,v,x,y,k;
    	rep(i,0,r)
    		rep(j,0,c){
    			rep(k,0,13){
    				if( g[i][j] == -1 )
    					continue;
    				if(g[i][j] & (1<<k)){
    					x = i + dir[k][0];
    					y = j + dir[k][1];
    					if( !_check(x,y) )
    						continue;
    					if( g[x][y] == -1)
    						continue;
    					u = i*c + j;
    					v = x*c + y;
    					if( (i+j)&1 )
    						add_edge(v,u);
    					else
    						add_edge(u,v);
    				}
    			}
    		}
    	return ;
    }
    int work()
    {
    	int i,j,u,v,tmp;
    	rep(i,0,r)
    		rep(j,0,c)
    			scanf("%d",&g[i][j]);
    	make_graph();
    	int cnt = r*c;
    	ans = 0;
    	rep(i,0,cnt){
    		CLR(vt,0);
    		if( dfs(i) )
    			++ans;
    	}
    	printf("%d. %d\n",tt,ans);
    	return 0;
    }
    int main()
    {
    	tt = 0;
    	while(scanf("%d%d",&r,&c)){
    		++tt;
    		if( r==0 || c == 0)
    			break;
    		init();
    		work();
    	}
    	return 0;
    }
    
  • 相关阅读:
    转:Nginx 日志文件切割
    nginx日志切割
    nginx日志配置
    Mongodb数据更新命令
    Android开发书籍推荐
    全面解读python web 程序的9种部署方式
    PowerDesinger15设置字体大小
    A* Pathfinding Project (Unity A*寻路插件) 使用教程
    jQuery的DOM操作之捕获和设置
    如何写一个好的方法
  • 原文地址:https://www.cnblogs.com/lvpengms/p/2508854.html
Copyright © 2011-2022 走看看