HOJ 1086 Don't Get Rooked 解题报告

HOJ 1086 Don't Get Rooked 解题报告

题目含义:给一个n*n的方阵,向其中填车,求使他们不能互相攻击的最大棋子数。

思路:

每一个格有两个元素组成,分别为第i行和第j列,那么可以把行数和列数分别看做两个集合X和Y中的点,他们之间由于每一个格而形成的一一对应的关系将其看做边。如果两条边相交,那么这两个格在同一行或同一列。

按照题目的意思,同一行或同一列只能放一个车,所以选出的边不能相交。

题中还有一个条件:可以放入障碍物。可以这样看,在障碍物那一行,在障碍物左右两边的格子不受行的限制,那么在表示行数的集合X中两边的格子应该对应不同的点,所以如果某格的左边是个障碍物,就再加一行,我们就把从该格开始这一行的所有格挪到新的一行上。同样,如果某格的上边是一个障碍物,就再加一列。

实现的时候用r[i]表示原来的第i行现在是第几行。

存好后,再求最大匹配即可得解。

总结:

对应关系:x坐标和y坐标的关系(即点)看作边,x坐标和y坐标看作点。

正如smallwood学长说的,做二分匹配关键是如何把一道题抽象成二分匹配,所以我尽量的将这道题的思路说明白,欢迎批评指正。

以下是代码:

 1  #include  < stdio.h >
 2  #include  < string .h >
 3   
 4  const   int  MAXN  =   500 ;
 5  int  uN, vN;                       //  u,v数目
 6  bool  g[MAXN][MAXN];                 //  g[i][j] 表示 xi与yj相连
 7  int  xM[MAXN], yM[MAXN];             //   输出量
 8  bool  chk[MAXN];                   //  辅助量 检查某轮 y[v]是否被check
 9   
10  bool  SearchPath( int  u)
11  {
12       int  v;
13       for (v  =   0 ; v  <  vN; v ++ )
14      {
15           if (g[u][v]  &&   ! chk[v])
16          {
17              chk[v]  =   true ;
18               if (yM[v]  ==   - 1   ||  SearchPath(yM[v]))
19              {
20                  yM[v]  =  u;
21                  xM[u]  =  v;
22                   return   true  ;
23              }
24          }
25      }
26       return   false ;
27  }
28   
29  int  MaxMatch()
30  {
31       int  u;
32       int  ret  =   0  ;
33   
34      memset(xM,  - 1 sizeof  (xM));
35      memset(yM,  - 1 sizeof  (yM));
36   
37       for (u  =   0 ; u  <  uN; u ++ )
38      {
39           if (xM[u]  ==   - 1 )
40          {
41              memset(chk,  false sizeof  (chk));
42               if (SearchPath(u))
43                  ret ++ ;
44          }
45      }
46       return  ret;
47  }
48  int  main()
49  {
50       int  n,row,col;
51       int  i,j;
52       char   in [ 5 ][ 5 ];
53       int  r[ 4 ],c[ 4 ];
54   
55       while (scanf( " %d " , & n) && n)
56      {
57           for (i  =   0 ; i  <   500 ; i ++ for (j  =   0 ; j  <   500 ; j ++ ) g[i][j]  =   0 ;
58   
59           for (i  =   0 ; i  <  n; i ++ )
60          {
61              scanf( "  %s " , in [i]);
62          }
63           for (i  =   0 ; i  <  n; i ++ )
64          {
65              r[i]  =  i;
66              c[i]  =  i;
67          }
68          row  =  n - 1 ;
69          col  =  n - 1 ;
70           for (i  =   0 ; i  <  n; i ++ )
71          {
72               for (j  =   0 ; j  <  n; j ++ )
73              {
74                   if ( in [i][j] == ' . ' )
75                  {
76                       if (i && in [i - 1 ][j] == ' X ' ) c[j]  =   ++ col;
77                       if (j && in [i][j - 1 ] == ' X ' ) r[i]  =   ++ row;
78                      g[r[i]][c[j]]  =   1 ;
79                  }
80              }
81          }
82          uN  =   ++ row;
83          vN  =   ++ col;
84          printf( " %d\n " ,MaxMatch());
85      }
86       return   0 ;
87  }

你可能感兴趣的:(HOJ 1086 Don't Get Rooked 解题报告)