題意:給你一個圖,圖裏有牆壁和空地,空地能夠放置一臺機關槍,機關槍能夠朝着四個方向發射,子彈不能穿透牆壁,可是射程無限,機關槍會被損壞若是被另外一臺機關槍的子彈打到,問你最多能放置多少臺機關槍;ios
解題思路:考慮每臺機關槍實際可以朝行和列兩個方向開火,根據貪心的想法,儘量不在某行和某列的交點放置,那麼若是咱們把行和列分紅x,y兩部分,每行中可以鏈接的空地看成x的一個頂點,每列中可以鏈接的空地看成y的一個頂點,問題轉換爲在二分圖中找沒有公共頂點的最大邊集,也就是二分圖最大匹配spa
代碼:code
#include<iostream> #include<algorithm> #include<cstring> #include<cstdio> using namespace std; int n; char s[10][10]; int match[50]; int visit[50]; int gra[50][50]; int row[50][50],col[50][50]; int c,r; int dfs(int u) { for(int i=1;i<c;i++) { if(gra[u][i]&&visit[i]==0) { visit[i]=1; if(match[i]==-1||dfs(match[i])) { match[i]=u; return 1; } } } return 0; } int main() { while(cin>>n&&n) { for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) cin>>s[i][j]; c=r=1; memset(row,-1,sizeof(row)); memset(col,-1,sizeof(col)); memset(match,-1,sizeof(match)); memset(visit,0,sizeof(visit)); memset(gra,0,sizeof(gra)); for(int i=1;i<=n;i++) { for(int j=1;j<=n;j++) { if(s[i][j]=='.'&&row[i][j]==-1)//找每行的頂點 { for(int k=j;k<=n;k++) if(s[i][k]=='.') row[i][k]=r; else//遇到牆壁結束 break; r++;//頂點+1 } } for(int j=1;j<=n;j++) { if(s[j][i]=='.'&&col[j][i]==-1) { for(int k=j;k<=n;k++) if(s[k][i]=='.') col[k][i]=c; else break; c++; } } } for(int i=1;i<=n;i++) { for(int j=1;j<=n;j++) { gra[row[i][j]][col[i][j]]=1; } } int ans=0; for(int i=1;i<r;i++) { memset(visit,0,sizeof(visit)); if(dfs(i)) { ans++; } } cout<<ans<<endl; } }