Your task is to write a program that, given a description of a map, calculates the maximum number of blockhouses that can be placed in the city in a legal configuration. InputThe input file contains one or more map descriptions, followed by a line containing the number 0 that signals the end of the file. Each map description begins with a line containing a positive integer n that is the size of the city; n will be at most 4. The next n lines each describe one row of the map, with a '.' indicating an open space and an uppercase 'X' indicating a wall. There are no spaces in the input file. OutputFor each test case, output one line containing the maximum number of blockhouses that can be placed in the city in a legal configuration. Sample Input4.X......XX......2XX.X3.X.X.X.X.3....XX.XX4................0 Sample Output51524題目大意:
給你一個n*n的矩陣,其中有一些點放置了障礙,然后問你最多放置多少的子使得每行每列有且只有一個除非中間有障礙
題目思路:
首先我們考慮最大匹配,但是中間有障礙也可以放,所以我們想到分成聯通快,即某一行或某一列里最大相連通的快,然后進行編號,最后其實我們可以發現如果某一行出現了一個障礙物使得改行增加了一個聯通快,實際上就相當于增加了一行,然后我們枚舉所有點如果改點是空白點,就以改點的行列聯通編號連邊,最后進行最大匹配就是我們要求的答案
AC代碼:
#include<cstring>#include<cstdio>const int maxn = 20;int link[maxn],a[maxn],b[maxn];bool vis[maxn],mp[maxn][maxn];int n,cnt,cnt1,flag,flag1;bool dfs(int u){ for(int i=1;i<=cnt1;i++){ if(!vis[i]&&mp[u][i]){ vis[i]=true; if(link[i]==-1||dfs(link[i])){ link[i]=u; return true; } } } return false;}int main(){ while(scanf("%d",&n),n){ memset(mp,false,sizeof(mp)); memset(link,-1,sizeof(link)); char str[5][5]; for(int i=0;i<n;i++)scanf("%s",str[i]); cnt=cnt1 = 1,flag=flag1=0; for(int i=0;i<n*n;i++){ int h = i/n,l=i%n; if(str[h][l]=='.')a[i]=cnt,flag=1; //a[i]記錄改點的行聯通編號 if(l==n-1||str[h][l]!='.') {if(flag)cnt++,flag=0;} //遇到障礙或一行的結束 if(str[l][h]=='.')b[l*n+h]=cnt1,flag1=1; //b[i]記錄改點的列聯通編號 if(l==n-1||str[l][h]!='.') {if(flag1)cnt1++,flag1=0;} //遇到障礙或一列的結束 } for(int i=0;i<n*n;i++)if(str[i/n][i%n]=='.')mp[a[i]][b[i]]=true; //改點的行聯通編號和列聯通編號連邊 int ans = 0; for(int i=1;i<=cnt;i++){ memset(vis,false,sizeof(vis)); if(dfs(i))ans++; } printf("%d/n",ans); } return 0;}
新聞熱點
疑難解答