zoukankan      html  css  js  c++  java
  • 长脖子鹿放置【洛谷P5030】二分图最大独立集变形题

    题目背景

    众周所知,在西洋棋中,我们有城堡、骑士、皇后、主教和长脖子鹿。

    题目描述

    如图所示,西洋棋的“长脖子鹿”,类似于中国象棋的马,但按照“目”字攻击,且没有中国象棋“别马腿”的规则。(因为长脖子鹿没有马腿)

    avatar

    给定一个N * MNM,的棋盘,有一些格子禁止放棋子。问棋盘上最多能放多少个不能互相攻击的长脖子鹿。

    输入格式

    输入的第一行为两个正整数NN,MM,KK。其中KK表示禁止放置长脖子鹿的格子数。

    22~第K+1K+1行每一行为两个整数Xi, YiXi,Yi,表示禁止放置的格子。

    输出格式

    一行一个正整数,表示最多能放置的长脖子鹿个数。

    输入输出样例

    输入 #1
    2 2 1
    1 1
    输出 #1
    3
    输入 #2
    /*额外提供一组数据*/
    8 7 5
    1 1
    5 4
    2 3
    4 7
    8 3
    输出 #2
    28
    思路:
    • 首先我们看,在棋盘上放棋子,让他们互相不能攻击,这明显是到二分图最大独立集(类似题骑士共存问题

    • 接着我们想怎样染色,第一下想的就是像棋盘那样按行列奇偶性来染,但是显然不对。于是我们发现一个惊人的问题,基数行和偶数行之间的棋子不会互相攻击!!!这样就好了,按行奇偶性来染色,跑个二分图最大独立集就行(二分图最大独立集=点数-最大匹配数)

    80分的代码QAQ:

     1 #include<bits/stdc++.h>
     2 
     3 //最大独立集=n-最小点覆盖
     4 using namespace std;
     5 #define maxn 6666
     6 int dx[]={1,1,3,3,-1,-1,-3,-3};
     7 int dy[]={3,-3,1,-1,3,-3,1,-1};
     8 int mp[maxn][maxn];
     9 int match[666*666];
    10 int vis[40001];
    11 int num[maxn][maxn];
    12 int flag=0;
    13 int n,m,k;
    14 int head[maxn*maxn];
    15 inline int read(){
    16     char c = getchar(); int x = 0, f = 1;
    17     while(c < '0' || c > '9') {if(c == '-') f = -1; c = getchar();}
    18     while(c >= '0' & c <= '9') x = x * 10 + c - '0', c = getchar();
    19     return x * f;
    20 }
    21 struct Edge{
    22     int to,next;
    23 }e[666*666*4];
    24 void  add(int u,int v){
    25     flag++;
    26     e[flag].to=v;
    27     e[flag].next=head[u];
    28     head[u]=flag;
    29 } 
    30 inline int cal_note(int xx,int yy){    //计算该格子的编号
    31     return (xx-1)*n+yy;
    32 }
    33 int dfs(int u){
    34     for(register int i=head[u];i;i=e[i].next){
    35         int temp=e[i].to;
    36         if(!vis[temp]){
    37             vis[temp]=1;
    38             if(match[temp]==0||dfs(match[temp]))
    39             {
    40                 match[temp]=u;
    41                 return 1;
    42             }
    43         }
    44     }
    45     return 0;
    46 } 
    47 int main(){
    48     //int n,m;
    49     //scanf("%d%d",&n,&m);
    50     n=read();
    51     m=read();
    52     k=read();
    53     int xx,yy;
    54     for(int i=1;i<=k;i++){
    55         //scanf("%d%d",&x,&y);
    56         xx=read();
    57         yy=read();
    58         mp[xx][yy]=1;// 标记不可以走到的点 
    59     }
    60     int cnt=0;
    61     /*for(int i=1;i<=n;i++)
    62         for(int j=1;j<=m;j++)
    63             num[i][j]=++cnt;        // 给每一个点编号 */
    64     for(register int i=1;i<=n;i+=2){
    65         for(register int j=1;j<=m;j++){
    66             if(mp[i][j])
    67                 continue;
    68             else{
    69                 int x=i;
    70                 int y=j;
    71                 for(int k=0;k<8;k++){
    72                     int tx=x+dx[k];
    73                     int ty=y+dy[k];
    74                     if(tx>=1&&ty>=1&&tx<=n&&ty<=m&&!mp[tx][ty]){
    75                         //v[num[x][y]].push_back(num[tx][ty]);
    76                         //v[num[tx][ty]].push_back(num[x][y]);
    77                         add(cal_note(i,j),cal_note(tx,ty));
    78                     //    add(cal_note(tx,ty),cal_note(x,y));
    79                     }
    80                 }
    81             }
    82         }
    83     }
    84     int ans=0;
    85     for(register int i=1;i<=n;i+=2){
    86         for(register int j=1;j<=m;j++){
    87             if(mp[i][j])
    88                 continue;
    89             memset(vis,0,sizeof(vis));
    90             if(dfs(cal_note(i,j)))
    91                 ans++;
    92         }
    93     }
    94     int res=n*m-k-ans;
    95     printf("%d
    ",res);
    96     return 0;
    97 } 
  • 相关阅读:
    vim复制
    嵌入式Linux学习(二)
    (Java实现) 洛谷 P1042 乒乓球
    (Java实现) 洛谷 P1042 乒乓球
    (Java实现) 洛谷 P1071 潜伏者
    (Java实现) 洛谷 P1071 潜伏者
    (Java实现) 洛谷 P1025 数的划分
    (Java实现)洛谷 P1093 奖学金
    (Java实现)洛谷 P1093 奖学金
    Java实现 洛谷 P1064 金明的预算方案
  • 原文地址:https://www.cnblogs.com/pengge666/p/11626228.html
Copyright © 2011-2022 走看看