hrbust 1697 国际象棋【二分匹配】

来源:互联网 发布:淘宝怎么判定定制产品 编辑:程序博客网 时间:2024/05/16 02:45

国际象棋Time Limit: 1000 MSMemory Limit: 32768 KTotal Submit: 45(18 users)Total Accepted: 21(17 users)Rating: Special Judge: NoDescription

国际象棋的棋盘是8*8的。一个骑士可以攻击到8个位置(和中国象棋的马的走法类似)。

在一个古老的游戏中,游戏者可以把一个骑士放在棋盘上,骑士就控制了它所在的位置。同时,骄傲的骑士可以从它可攻击的8个位置中,选择一个,作为它的控制领域。也就是说,一个骑士最多可以事实上控制棋盘中的两个格子。

游戏允许游戏者任意放置骑士,并且任意安排这些骑士所控制的格子。最后的目的是要用最少的骑士控制棋盘上的每一个格子。

小胖子在《巴多兰克斯经》上发现了这个古老的游戏,他哈哈大笑,很快就完成了这个简单的游戏。

这时候大胖子来串门了,他看了看这个游戏说:“太弱智了。干脆改成n*n的棋盘吧!”他想了想还不满意,又说:“另外还要把某些格子挖掉!”当然,这些挖掉的格子既不能放骑士,也不需要任何骑士去控制它。

这么一改,可把小胖子难住了。聪明的你能解决这个问题吗?

Input

    本题有多组测试数据,每组测试数据占若干行。

    每组数据的第一行输入一个正整数n(n<=20)。接下来若干行,每行输入两个数a, b,表示第a行第b列的格子被挖掉了,直到0 0结束。

Output

仅一个整数并且换行,即最少放置的骑士数。

Sample Input

3

2 2

0 0

Sample Output4Authorsunshine@hrbust

思路:


1、经典的二分匹配模型,将放置的骑士作为左集合,将骑士选择控制的点作为右集合。然后枚举所有点,并且枚举出其八个可以控制的点,将其间连一条边(现在建立的相当于双向边)。


2、然后将建好的图跑一遍最大匹配匈牙利算法,因为建立的是双向边,那么其解/2==放置的骑士能够同时控制两个格子的数量。


3、那么其没有能够匹配的格子数(只能控制自己放置的位子上的骑士的个数)就是n*n-最大匹配数-去掉的格子数。


4、那么ans=最大匹配数/2+n*n-最大匹配数-去掉的格子数。


Ac代码:

#include<stdio.h>#include<string.h>#include<vector>using namespace std;int a[55][55];int match[55*55];int vis[55*55];vector<int >mp[55*55];int fx[8]={-2,-1,1,2,2,1,-1,-2};int fy[8]={1,2,2,1,-1,-2,-2,-1};int n;void getmap(){    for(int i=1;i<=n;i++)    {        for(int j=1;j<=n;j++)        {            if(a[i][j]==1)            {                for(int k=0;k<8;k++)                {                    int x=i+fx[k];                    int y=j+fy[k];                    if(x>=1&&x<=n&&y>=1&&y<=n)                    {                        if(a[x][y]==1)                        {                            mp[(i-1)*n+j].push_back((x-1)*n+y);                        }                    }                }            }        }    }}int find(int u){    for(int i=0;i<mp[u].size();i++)    {        int v=mp[u][i];        if(vis[v]==0)        {            vis[v]=1;            if(match[v]==-1||find(match[v]))            {                match[v]=u;                return 1;            }        }    }    return 0;}int Slove(){    memset(match,-1,sizeof(match));    int output=0;    for(int i=1;i<=n*n;i++)    {        memset(vis,0,sizeof(vis));        if(find(i)==1)output++;    }    return output;}int main(){    while(~scanf("%d",&n))    {        int sum=0;        for(int i=1;i<=n;i++)        {            for(int j=1;j<=n;j++)            {                a[i][j]=1;            }        }        for(int i=1;i<=n*n;i++)mp[i].clear();        while(1)        {            int x,y;            scanf("%d%d",&x,&y);            if(x==0&&y==0)break;            a[x][y]=0;            sum++;        }        getmap();        int ans=Slove();        printf("%d\n",ans/2+n*n-ans-sum);    }}



0 0