HDU1045

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1045

解题思路:

  首先,这题的数据范围很小,可以暴搜,略过不表。此处主要讲二分匹配作法。

  思路来源于网络。

  对于同一行上没有石头相隔的相连格子,我们将其编成一个号,得到一个号码集合X;同一列上没有石头相隔的相连格子也编成一个号,得到另一个号码集合Y。X,Y中的每个号码就代表某一个或者几个格子,如果X中的一个号码对应的格子和Y中的一个号码对应的格子有重叠,那么就记这两个号码相匹配。最后只要求出X和Y的最大匹配数即可得出答案。

  

  图片来源于:http://blog.csdn.net/job_yi/article/details/10172925

AC代码:

 1 #include <iostream>
 2 #include <cstring>
 3 #include <cstdio>
 4 using namespace std;
 5 char Map[5][5];
 6 int x[5][5],y[5][5];
 7 bool link[20][20],vis[20];
 8 int y_x[20];
 9 int n;
10 int xi,yi;
11 bool finds(int x){
12     for(int i=1;i<=yi;i++){
13         if(link[x][i]&&!vis[i]){
14             vis[i]=true;
15             if(y_x[i]==0||finds(y_x[i])){
16                 y_x[i]=x;
17                 return true;
18             }
19         }
20     }
21     return false;
22 }
23 int main(){
24    while(scanf("%d",&n)==1&&n){
25         memset(y_x,0,sizeof(y_x));
26         memset(link,0,sizeof(link));
27         memset(x,0,sizeof(x));
28         memset(y,0,sizeof(y));
29         for(int i=0;i<n;i++)    scanf("%s",Map[i]);
30         xi=yi=0;
31         bool used=true;
32         for(int i=0;i<n;i++){
33             if(used){
34                 xi++;  used=false;
35             }
36             for(int j=0;j<n;j++){
37                 if(Map[i][j]=='X'&&used){
38                     used=false;
39                     xi++;
40                 }
41                 else if(Map[i][j]=='.'){
42                     x[i][j]=xi;    used=true;
43                 }
44             }
45             if(i==n-1&&!used)   xi--;
46         }
47         used=true;
48         for(int j=0;j<n;j++){
49             if(used){
50                 yi++;   used=false;
51             }
52             for(int i=0;i<n;i++){
53                 if(Map[i][j]=='X'&&used){
54                     yi++;  used=false;
55                 }
56                 else if(Map[i][j]=='.'){
57                     y[i][j]=yi;    used=true;
58                 }
59             }
60             if(j==n-1&&!used)   yi--;
61         }
62         for(int i=0;i<n;i++){
63             for(int j=0;j<n;j++){
64                 link[x[i][j]][y[i][j]]=true;
65             }
66         }
67         int ans=0;
68         for(int i=1;i<=xi;i++){
69             memset(vis,0,sizeof(vis));
70             if(finds(i))    ans++;
71         }
72         printf("%d\n",ans);
73    }
74     return 0;
75 }

 

posted @ 2017-08-28 21:29  Blogggggg  阅读(146)  评论(0编辑  收藏  举报