I - Hiding Gold
You are given a 2Dboard where in some cells there are gold. You want to fill the board with 2x 1 dominoes such that all gold are covered. You may use the dominoesvertically or horizontally and the dominoes may overlap. All you have to do isto cover the gold with least number of dominoes.
In the picture,the golden cells denote that the cells contain gold, and the blue ones denotethe 2 x 1 dominoes. The dominoes may overlap, as we alreadysaid, as shown in the picture. In reality the dominoes will cover the full 2x 1 cells; we showed small dominoes just to show how to cover the goldwith 11 dominoes.
Input
Input starts withan integer T (≤ 50), denoting the number of test cases.
Each case startswith a row containing two integers m (1 ≤ m ≤ 20) and n(1 ≤ n ≤ 20) and m * n > 1. Here mrepresentsthe number of rows, and n represents the number of columns.Then there will be m lines, each containing ncharactersfrom the set ['*','o']. A '*' character symbolizesthe cells which contains a gold, whereas an 'o' characterrepresents empty cells.
Output
For each caseprint the case number and the minimum number of dominoes necessary to cover allgold ('*' 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
题意:在一个n*m的地图上,有两种字符* o ,其中*代表金矿、o代表空。现在要求你用最少的 1*2 (或者 2*1)的材料盖住所有的金矿。
思路:先将题中所给的图每一点用搜索的方式存成一张0,1标记的连通图,用t1记录金矿的个数,然后匈牙利算法计算连通的点的个数存入sum,然后用t1-sum/2计算出需要的最小需要覆盖数。
#include<stdio.h>
#include<string.h>
int a[500][500],b[500],match[500];
char s[100][100];
int m,n;
int dfs(int s)//匈牙利算法
{
int i;
for(i=1;i<=m*n;i++)
{
if(b[i]==0&&a[s][i]==1)
{
b[i]=1;
if(match[i]==-1||dfs(match[i]))
{
match[i]=s;
// match[s]=i;
return 1;
}
}
}
return 0;
}
int main()
{
int i,j,k,t,t1,t2,t3,t4=1,x,y,sum;
int next[4][2]={{0,1},{1,0},{-1,0},{0,-1}};
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&n,&m);
memset(a,0,sizeof(a));
memset(s,0,sizeof(s));
memset(match,-1,sizeof(match));
for(i=1;i<=n;i++)
{
scanf("%s",s[i]+1);
}
t1=0;
for(i=1;i<=n;i++)
{
for(j=1;j<=m;j++)
{
if(s[i][j]=='*')
{
t1++;
for(k=0;k<=3;k++)//搜索四个方向
{
x=i+next[k][0];
y=j+next[k][1];
if(x>n||y>m||x<1||y<1)
continue;
if(s[x][y]=='*')
{
a[(i-1)*m+j][(x-1)*m+y]=1;
}
}
}
}
}
sum=0;
for(i=1;i<=m*n;i++)
{
memset(b,0,sizeof(b));
if(dfs(i))
sum++;
}
printf("Case %d: %d\n",t4++,t1-sum/2);
}
return 0;
}