zoukankan      html  css  js  c++  java
  • 洛谷P1263 || 巴蜀2311 宫廷守卫

    题目描述

    从前有一个王国,这个王国的城堡是一个矩形,被分为M×N个方格。一些方格是墙,而另一些是空地。这个王国的国王在城堡里设了一些陷阱,每个陷阱占据一块空地。

    一天,国王决定在城堡里布置守卫,他希望安排尽量多的守卫。守卫们都是经过严格训练的,所以一旦他们发现同行或同列中有人的话,他们立即向那人射 击。因此,国王希望能够合理地布置守卫,使他们互相之间不能看见,这样他们就不可能互相射击了。守卫们只能被布置在空地上,不能被布置在陷阱或墙上,且一 块空地只能布置一个守卫。如果两个守卫在同一行或同一列,并且他们之间没有墙的话,他们就能互相看见。(守卫就像象棋里的车一样)

    你的任务是写一个程序,根据给定的城堡,计算最多可布置多少个守卫,并设计出布置的方案。

    输入输出格式

    输入格式:

    第一行两个整数M和N(1≤M,N≤200),表示城堡的规模。

    接下来M行N列的整数,描述的是城堡的地形。第i行j列的数用ai,j表示。

    ai,j=0,表示方格[i,j]是一块空地;

    ai,j=1,表示方格[i,j]是一个陷阱;

    ai,j=2,表示方格[i,j]是墙。

    输出格式:

    第一行一个整数K,表示最多可布置K个守卫。

    此后K行,每行两个整数xi和yi,描述一个守卫的位置。

    输入输出样例

    输入样例#1:
    3 4
    2 0 0 0
    2 2 2 1
    0 1 0 2
    
    输出样例#1:
    2
    1 2
    3 3
    

    说明

    样例数据如图5-2(黑色方格为墙,白色方格为空地,圆圈为陷阱,G表示守卫)

    刚开始的写法是BFS出每个联通块,单独处理。

    ↑明显不对

    后来发现可以把被墙隔开的同一行当成两行处理,列同理。

    然后二分图匹配坐标即可。

    对二分图的理解还是不透彻啊……

    (代码仅提供思路,不保证正确性)(没有SPJ程序)

    (巴蜀OJ上只要求输出最多守卫数量,已AC)

      1 /*By SilverN*/
      2 #include<iostream>
      3 #include<cstdio>
      4 #include<cmath>
      5 #include<cstring>
      6 #include<algorithm>
      7 #define LL long long
      8 using namespace std;
      9 const int mxn=2200;
     10 int read(){
     11     int x=0,f=1;char ch=getchar();
     12     while(ch<'0' || ch>'9'){if(ch=='-')f=-1;ch=getchar();}
     13     while(ch>='0' && ch<='9'){x=x*10+ch-'0';ch=getchar();}
     14     return x*f;
     15 }
     16 struct edge{
     17     int v,nxt;
     18 }e[mxn*100];
     19 int hd[mxn*10],mct=0;
     20 void add_edge(int u,int v){
     21     e[++mct].v=v;e[mct].nxt=hd[u];hd[u]=mct;return;
     22 }
     23 int mp[mxn][mxn];
     24 int idx,idy;
     25 int hs[mxn][mxn];
     26 int aidx[mxn*10],aidy[mxn*10];
     27 int link[mxn*10],vis[mxn*10];
     28 //
     29 int n,m,ans=0;
     30 bool DFS(int u){
     31     for(int i=hd[u];i;i=e[i].nxt){
     32         int v=e[i].v;
     33         if(!vis[v]){
     34             vis[v]=1;
     35             if(link[v]==-1 || DFS(link[v])){
     36                 link[v]=u;
     37                 return 1;
     38             }
     39         }
     40     }
     41     return 0;
     42 }
     43 void solve(){
     44     memset(link,-1,sizeof link);
     45     for(int i=1;i<=idx;i++){
     46         memset(vis,0,sizeof vis);
     47         if(DFS(i))ans++;
     48     }
     49     return;
     50 }
     51 void init(){
     52     int i,j;
     53     bool flag=1;
     54     for(i=1;i<=m;i++){
     55         flag=1;
     56         for(j=1;j<=n;j++){
     57             if(mp[i][j]==2){flag=1;continue;}
     58             if(flag){
     59                 ++idx;
     60                 aidx[idx]=i;
     61                 flag=0;
     62             }
     63             hs[i][j]=idx;
     64         }
     65     }
     66     idy=idx;
     67     for(j=1;j<=n;j++){
     68         flag=1;
     69         for(i=1;i<=m;i++){
     70             if(mp[i][j]==2){flag=1;continue;}
     71             if(flag){
     72                 ++idy;
     73                 aidy[idy]=j;
     74                 flag=0;
     75             }
     76             if(mp[i][j])continue;
     77             add_edge(idy,hs[i][j]);
     78             add_edge(hs[i][j],idy);
     79 //            printf("%d %d:%d
    ",i,j,idy);
     80         }
     81     }
     82     return;
     83 }
     84 int main(){
     85     m=read();n=read();
     86     int i,j;
     87     for(i=1;i<=m;i++)
     88         for(j=1;j<=n;j++)
     89             mp[i][j]=read();
     90     init();
     91     solve();
     92 /*    for(i=1;i<=m;i++){
     93      for(j=1;j<=n;j++){
     94          printf("%d ",hs[i][j]);
     95      }
     96      printf("
    ");
     97     }*/
     98     printf("%d
    ",ans);
     99     for(i=idx+1;i<=idy;i++){
    100         if(link[i]!=-1)printf("%d %d
    ",aidx[link[i]],aidy[i]);
    101     }
    102     return 0;    
    103 }
  • 相关阅读:
    选择结构
    算法和流程图
    存储信息和信息运算
    计算机组成原理
    计算机硬件组装
    认识计算机硬件
    认识操作系统
    DOS简介
    计算机软件知识
    易企cms截取字段方法
  • 原文地址:https://www.cnblogs.com/SilverNebula/p/6035375.html
Copyright © 2011-2022 走看看