题意:给出一个图,其中有 . 和 X 两种,. 为通路,X表示墙,在其中放炸弹,然后炸弹不能穿过墙,问你最多在图中可以放多少个炸弹?
这个题建图有点复杂orz。
建图,首先把每一行中的可以放一个炸弹的一块区域标记为同一个数字,数字不重复,然后列做相同的处理,即缩点!
缩点之后原图矩阵中每个点都对用一个行数字和一个列数字,然后按照这两个数字进行二分匹配,其相同值只取一个,得到的结果就是ans。
1 #include<iostream> 2 #include<cstring> 3 #include<iostream> 4 #include<algorithm> 5 #define maxn 10 6 using namespace std; 7 int n; 8 int cnt_row,cnt_col; 9 char map[maxn][maxn]; 10 int line[maxn][maxn],row[maxn][maxn],col[maxn][maxn],match[maxn],used[maxn]; 11 int dfs(int x){ 12 for (int i=0;i<cnt_col;i++){ 13 if (line[x][i]==1 && !used[i]){ 14 used[i]=1; 15 if (match[i]==-1 || dfs(match[i])){ 16 match[i]=x; 17 return 1; 18 } 19 } 20 } 21 return 0; 22 } 23 int main(){ 24 while (cin >> n && n){ 25 for (int i=0;i<n;i++){ 26 for (int j=0;j<n;j++){ 27 cin >> map[i][j]; 28 } 29 } 30 memset(row,-1,sizeof(row)); 31 memset(col,-1,sizeof(col)); 32 cnt_row=0,cnt_col=0; 33 for (int i=0;i<n;i++){ 34 for (int j=0;j<n;j++){ 35 if (map[i][j]=='.' && row[i][j]==-1){ 36 for (int k=j;map[i][k]=='.' && k<n;k++) row[i][k]=cnt_row; 37 cnt_row++; 38 } 39 if (map[j][i]=='.' && col[j][i]==-1){ 40 for (int k=j;map[k][i]=='.' && k<n;k++) col[k][i]=cnt_col; 41 cnt_col++; 42 } 43 } 44 } 45 memset(line,0,sizeof(line)); 46 for (int i=0;i<n;i++){ 47 for (int j=0;j<n;j++){ 48 if (map[i][j]=='.' && row[i][j]!=-1 && col[i][j]!=-1) 49 line[row[i][j]][col[i][j]]=1; 50 } 51 } 52 int ans=0; 53 memset(match,-1,sizeof(match)); 54 for (int i=0;i<cnt_row;i++){ 55 memset(used,0,sizeof(used)); 56 if (dfs(i)) ans++; 57 } 58 cout << ans << endl; 59 } 60 return 0; 61 }