sgu 190 分类: sgu 2015-04...


首先可以观察出,每张骨牌可以覆盖相邻的两个方格,
即一张骨牌可以覆盖 两个横纵坐标之和的奇偶性不同的方格。

solution:首先根据横纵坐标之和的奇偶性对每个方格染色,然后根据骨牌放置方式连边,最后二分图匹配即可。


#include<map>
#include<queue>
#include<stack>
#include<utility>
#include<string>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<ctime>
#include<cmath>
#include<iostream>
#include<algorithm>
#define Px first
#define Py second
#define Mp(x,y) std::make_pair(x,y)

const int MAXN = 45, SIZE = MAXN*MAXN, Node = SIZE>>1;
struct Edge{int v,next;Edge(int v = 0,int next = 0):v(v),next(next){}};

int n , m; 
bool map[MAXN][MAXN];

int nx = 0,ny = 0; bool flag;
int num[MAXN][MAXN] = {0};
std::pair<int,int>cx[Node],cy[Node];

int el = 0,head[Node] = {0};Edge edge[SIZE];

bool hash[Node];int link[Node] = {0};

int move[4][2] = {{0,1},{1,0},{0,-1},{-1,0}};

void NewEdge(int u,int v)
{++el, edge[el] = Edge(v,head[u]), head[u] = el;}

bool Find(int a)
{
    for(int i = head[a]; i ; i = edge[i].next)
    {
        int p = edge[i].v;

        if(hash[p]) continue;

        hash[p] = true;
        if(!link[p] || Find(link[p])) 
        {
            link[p] = a;
            return true;
        }
    }
    return false;
}

int main()
{
#ifndef ONLINE_JUDGE
    freopen("sgu190.in","r",stdin);
    freopen("sgu190.out","w",stdout);
#endif

    std::cin >> n >> m;

    memset(map,true,sizeof(map));

    for(int i = 1; i <= n; i++)
       map[0][i] = map[n+1][i] = map[i][0] = map[n+1][i] = false;

    for(int i = 1,a,b; i <= m; i++)
    {
      std::cin >> a >> b;
      map[a][b] = false;
    }

    for(int i = 1; i <= n; i++)
      for(int j = 1; j <= n; j++)
        if(map[i][j] == true)
          if((i+j)&1) num[i][j] = ++ny, cy[ny] = Mp(i,j);
          else num[i][j] = ++nx, cx[nx] = Mp(i,j);

    for(int i = 1; i <= n; i++)
      for(int j = 1; j <= n; j++)
       if(!((i+j)&1) && num[i][j])
         for(int k = 0; k < 4; k++)
        {
            int ii = i+move[k][0], jj = j+move[k][1];
            if(num[ii][jj]) NewEdge(num[i][j],num[ii][jj]);
        }

    flag = true;

    if(nx != ny) flag = false;

    for(int i = 1; i <= nx && flag; i++)
      memset(hash,false,sizeof(hash)) ,flag = Find(i);

    if(flag)
    {
        int cnt1 = 0, cnt2 = 0; 

       std::cout << "Yes" << std::endl;

       for(int i = 1; i <= ny; i++)
       {
         std::pair<int,int>c1 = cx[link[i]],c2 = cy[i];
         if(c1.Px == c2.Px) cnt1++;
         if(c1.Py == c2.Py) cnt2++;
       }
       std::cout << cnt2 << std::endl;
       for(int i = 1; i <= ny; i++)
       {
         std::pair<int,int>c1 = cx[link[i]],c2 = cy[i];
         if(c1.Py == c2.Py)std::cout << std::min(c1.Px,c2.Px) << ' ' << c1.Py << std::endl;
       }
       std::cout << cnt1 << std::endl;
       for(int i = 1; i <= ny; i++)
       {
         std::pair<int,int>c1 = cx[link[i]],c2 = cy[i];
         if(c1.Px == c2.Px) std::cout << c1.Px << ' ' << std::min(c1.Py,c2.Py) << std::endl;
       }
    }
    else
       std::cout << "No" << std::endl;


#ifndef ONLINE_JUDGE
    fclose(stdin);
    fclose(stdout);
#endif
    return 0;           
}

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

转载于:https://www.cnblogs.com/dashgua/p/4723038.html

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值