InputInput will include several test cases. The first line of a test case contains two integers N and M, representing, respectively, the number of rows and columns of the land (1 <= N, M <= 100). The second line will contain an integer K indicating the number of squares that have been turned into ponds ( (N x M) - K <= 50). Each of the next K lines contains two integers X and Y describing the position of a square which was turned into a pond (1 <= X <= N and 1 <= Y <= M). The end of input is indicated by N = M = 0. OutputFor each test case in the input your program should first output one line, containing an integer p representing the maximum number of properties which can be sold. The next p lines specify each pair of squares which can be sold simultaneity. If there are more than one solution, anyone is acceptable. there is a blank line after each test case. See sample below for clarification of the output format. Sample Input4 461 11 42 24 14 24 44 344 23 22 23 10 0 Sample Output4(1,2)--(1,3)(2,1)--(3,1)(2,3)--(3,3)(2,4)--(3,4)3(1,1)--(2,1)(1,2)--(1,3)(2,3)--(3,3) 題目大意:給你一個n*m的矩陣,其中有些格子不能填東西,然后問你在空白處最多能填多少個1*2的方塊
題目思路:
首先我們想到1*2的方塊就是相鄰兩個格子的匹配,所以我們可以考慮將相鄰格子建邊,做最大匹配,最后的答案就是我們要求的,然后我們考慮如何構造二分圖,應為這是個二維坐標,所以我們為了方便可以把二維坐標轉換成一維坐標,然后枚舉所有格子,分成奇偶,行列相加為偶數的和行列相加為奇數的連邊,因為兩個相鄰格子的奇偶不同,然后進行最大匹配,集合的大小就是n*m,最后最大匹配的答案就是我們要求的,對于輸出邊,我們可以從link數組當中記錄的連接邊的情況來輸出,我們枚舉i,
如果link[i]不等于-1,這時候我們就知道i和link[i]之間有一條邊
AC代碼:
#include<cstring>#include<cstdio>#include<vector>using std::vector;const int maxn = 2e4+100;bool vis[maxn],mp[205][205];int link[maxn];int n,m,k;vector<int>edge[maxn];bool dfs(int u){ for(int i=0;i<edge[u].size();i++){ int v = edge[u][i]; if(!vis[v]){ vis[v]=true; if(link[v]==-1||dfs(link[v])){ link[v]=u; return true; } } } return false;}void graph(){ for(int i=1;i<=n*m;i++)edge[i].clear(); for(int i=1;i<=n;i++){ for(int j=1;j<=m;j++){ int x = (i-1)*m+j; if(!mp[i][j]&&(i+j)%2){ if(j+1<=m&&!mp[i][j+1]){ //枚舉偶數點的四個方向 edge[x].push_back(x+1); } if(i+1<=n&&!mp[i+1][j]){ edge[x].push_back(x+m); } if(j-1>=1&&!mp[i][j-1]){ edge[x].push_back(x-1); } if(i-1>=1&&!mp[i-1][j]){ edge[x].push_back(x-m); } } } }}int main(){ while(scanf("%d%d",&n,&m),n+m){ scanf("%d",&k); memset(link,-1,sizeof(link)); memset(mp,false,sizeof(mp)); for(int j=1;j<=k;j++) { int x,y;scanf("%d%d",&x,&y); mp[x][y]=true; } graph(); int ans = 0; for(int i=1;i<=n*m;i++){ memset(vis,false,sizeof(vis)); if(dfs(i))ans++; } printf("%d/n",ans); if(ans>0){ for(int i=1;i<=n*m;i++){ //枚舉連接的邊 int j = link[i]; if(link[i]!=-1){ int x = i,y = j; printf("(%d,%d)--(%d,%d)/n",(x-1)/m+1,(x-1)%m+1,(y-1)/m+1,(y-1)%m+1); } } } printf("/n"); } return 0;}
新聞熱點
疑難解答