題意:給出一個圖,其中有 . 和 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 }
?