JZOJ 3457. 【NOIP2013模拟联考3】沙耶的玩偶(doll)

题目

Description

在美鱼和理树后援团拯救世界的同时,外表柔弱的理树也开始坚强起来,思考着离开这个世界的办法。误打误撞地,她遇上了正在教室破坏课桌打开迷宫入口的沙耶。沙耶告诉理树,这个世界的出口就是这个迷宫的出口。于是理树毫不犹豫地跟沙耶一起跳进了迷宫。在迷宫里,两个女孩子互帮互助,一会儿割绳子,一会儿泡温泉,一会儿雕冰块,跌跌撞撞地走到了终点。不出所料,终点也有一个机关在等着她们。

终点的机关是一个立着的m*n 的方格棋盘,在有些格子上放了一个玩偶,而有些地方直接挖了个大坑。只有取走所有玩偶才能打开出口。但是,由于奇怪的设定,理树和沙耶不能直接触碰玩偶,他们需要操纵机器人来收集它。机器人的走法很奇怪,和国际象棋的马有点像,只不过马可以走任意方向的1*2 路线,它们只会由上往下走r*c(或c*r)的路线,不能回头。而机器人一旦经过一个有玩偶的格子,那个格子上的玩偶将被回收,并且在机器人离开时,那个格子会变成一个坑。理树可以把机器人放在任何一个有玩偶的格子上作为起点,也可以在任何一个有玩偶的格子回收机器人。机器人行走可以视为瞬移,只不过每一次设置新起点都会消耗1 时间。并且,有坑的格子不能落脚。

就在这个紧要关头,玩偶狂热爱好者的沙耶却流着口水智商归0。理树不得不转而求助你,帮忙计算出最少多少时间就能收集到所有玩偶。
 

Input

第一行包含4 个整数M、N、R、C,意义见问题描述。接下来M 行每行一个长度为N 的

字符串。如果某个字符是'.',表示这个地方有一个玩偶;如果这个字符是'x',表示这个地

方是坑。

Output

输出一个整数,表示最短时间。
 

Sample Input

3 3 1 2
...
.x.
...

Sample Output

4
 

Data Constraint

30%的数据中,1<=M,N<=4,1<=R,C<=3。

70%的数据中,1<=M<=20,1<=N<=4,1<=R,C<=3。

100%的数据中,1<=M,N<=50,1<=R,C<=10。
 

Hint

 

分析

 

  • 首先标点,然后跑二分图
  • 答案=空格数-最大匹配

 

代码

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<iostream>
 4 #include<vector>
 5 using namespace std;
 6 long long n,m,x,y,ans,link[100001],s[205][205],p,ss;
 7 vector<int> f[10001];
 8 bool cover[100001];
 9 int map[100][100],rk[100][100];
10 bool find(int i)
11 {
12      for (int k=0;k<f[i].size();k++)
13        if (!cover[f[i][k]])
14        {
15            int j=f[i][k];
16            cover[j]=true;
17            int q=link[j];
18            link[j]=i;
19            if (q==0||find(q)) return true;
20            link[j]=q;
21         }
22     return false;
23 }
24 int main()
25 {
26     int n,m,r,c;
27     cin>>n>>m>>r>>c;
28     char num;
29     int fx[4][2]={{r,c},{c,r},{r,-c},{c,-r}};
30     int cnt=0,tot=0;
31     for (int i=1;i<=n;i++)
32       for (int j=1;j<=m;j++)
33       {
34            cin>>num;
35            if (num=='.') map[i][j]=1,rk[i][j]=++cnt;
36            else tot++;
37       }
38     for (int i=1;i<=n;i++)
39       for (int j=1;j<=m;j++)
40            for (int k=0;k<4;k++)
41            {
42                 int ax=i+fx[k][0],ay=j+fx[k][1];
43                 if (ax>n||ay>m||ax<1||ay<1||!map[ax][ay]) continue;
44                 f[rk[i][j]].push_back(rk[ax][ay]);
45            }
46      int ans=0;
47      for (int i=1;i<=n;i++)
48      {
49          for (int j=1;j<=m;j++)
50          {
51              if (map[i][j]==1)
52              {
53                  memset(cover,0,sizeof(cover));
54                 ans+=find(rk[i][j]);
55              }
56          }
57      }
58      cout<<n*m-tot-ans;                                  
59 }

 

posted @ 2019-08-16 08:40  Melted_czj  阅读(168)  评论(0编辑  收藏  举报
body { background-color:whitesmoke; } // 修改背景颜色为半透明 #home,#sideBarMain>div,#blog-sidecolumn>div>div,.catListView{ background-color:rgba(255,255,255,0); } // 修改其他边框的颜色