light oj 1152 Hiding Gold

题目:

You are given a 2D board where in some cells there are gold. You want to fill the board with 2 x 1 dominoes such that all gold are covered. You may use the dominoes vertically or horizontally and the dominoes may overlap. All you have to do is to cover the gold with least number of dominoes.

 

In the picture, the golden cells denote that the cells contain gold, and the blue ones denote the 2 x 1 dominoes. The dominoes may overlap, as we already said, as shown in the picture. In reality the dominoes will cover the full 2 x 1 cells; we showed small dominoes just to show how to cover the gold with 11 dominoes.

Input

Input starts with an integer T (≤ 50), denoting the number of test cases.

Each case starts with a row containing two integers m (1 ≤ m ≤ 20) and n (1 ≤ n ≤ 20)and m * n > 1. Here m represents the number of rows, and n represents the number of columns. Then there will be m lines, each containing n characters from the set ['*','o']. A '*'character symbolizes the cells which contains a gold, whereas an 'o' character represents empty cells.

Output

For each case print the case number and the minimum number of dominoes necessary to cover all gold ('*' entries) in the given board.

Sample Input

2

5 8

oo**oooo

*oo*ooo*

******oo

*o*oo*oo

******oo

3 4

**oo

**oo

*oo*

Sample Output

Case 1: 11

Case 2: 4

题意描述:

输入矩阵,‘*’表示金矿,‘o’表示空地,现在使用2*1或者1*2的材料将这些金矿盖住,问至少需要几块这样的材料。

解题思路:

很容易想到,不管使用一块2*1的材料还是1*2的材料,他们所盖住的两个金矿一定是一个奇数位,一个偶数位,那么采用二分图的思想建模,将所有的金矿进行编号,使用匈牙利算法

进行匹配,求出最大匹配数即可。

AC代码:

 1 #include<stdio.h>
 2 #include<string.h>
 3 char G[25][25];
 4 int r,c,count,g[25][25],map[300][300],book[500],match[500];
 5 void get_map();
 6 int maxmatch();
 7 int path(int u);
 8 int main()
 9 {
10     int T,i,j,t=1;
11     scanf("%d",&T);
12     while(T--)
13     {
14         scanf("%d%d",&r,&c);
15         for(i=0;i<r;i++)
16             scanf("%s",G[i]);
17         memset(g,0,sizeof(g));
18         count=0;
19         for(i=0;i<r;i++)
20             for(j=0;j<c;j++)
21                 if(G[i][j]=='*')
22                 g[i][j]= ++count;
23         memset(map,0,sizeof(map));
24         get_map();
25         /*for(i=1;i<=count;i++)
26         {
27             for(j=1;j<=count;j++)
28                 printf("%3d",map[i][j]);
29             printf("\n");
30         }*/
31         //printf("%d\n",maxmatch());
32         printf("Case %d: %d\n",t++,count-maxmatch());
33         /*for(i=1;i<=count;i++)
34             printf("%d和%d匹配\n",i,match[i]);*/
35     }
36     return 0;
37 }
38 void get_map()
39 {
40     int i,j,k,tx,ty;
41     int next[4][2]={0,1,1,0,0,-1,-1,0};
42     for(i=0;i<r;i++)
43     {
44         for(j=0;j<c;j++)
45         {
46             if(G[i][j]=='*')
47             {
48                 for(k=0;k<=3;k++)
49                 {
50                     tx=i+next[k][0];
51                     ty=j+next[k][1];
52                     if(tx < 0 || tx >= r || ty < 0 || ty >= c)
53                     continue;
54                     if(G[tx][ty]=='*')
55                     map[g[i][j]][g[tx][ty]]=1;
56                 }
57             }
58         }
59     }
60 }
61 int maxmatch()
62 {
63     int i,res=0;
64     memset(match,0,sizeof(match));
65     for(i=1;i<=count;i++)
66     {
67         if(!match[i])
68         {
69             memset(book,0,sizeof(book));
70             res += path(i);    
71         }
72     }
73     return res;//返回最大匹配数 
74 }
75 int path(int u)
76 {
77     int i;
78     for(i=1;i<=count;i++)
79     {
80         if(map[u][i] && !book[i])
81         {
82             book[i]=1;
83             if(!match[i] || path(match[i]))
84             {
85                 match[i]=u;
86                 match[u]=i;//避免重复 
87                 return 1;
88             }
89         }
90     }
91     return 0;
92 }

 

posted @ 2017-08-15 09:27  Reqaw  阅读(385)  评论(0编辑  收藏  举报