poj Muddy Fields
阿新 • • 發佈:2017-06-17
poj 求解 back str pos data 首頁 return print
Muddy Fields
原題去我創的專題裏找。在文件夾首頁。
題目:
給出N*M矩陣。當中*表示泥土,.表示小草。要你用最少的木板把泥土覆蓋。
木板長度不限,可是僅僅能水平和豎直。
行列式二分匹配配。是poj3041建圖的加強版。
算法:
由poj3041的建圖能夠得到靈感。即把木板當作頂點,X軸,Y軸當作邊。求解最小頂點覆蓋。
3041的激光束不存在障礙物的問題,而這題卻有不能壓壞小草的限制。
我們能夠換個角度思考,既然不能壓壞小草。那就相當於該激光束到達這裏必須停止了。所以。我們就以小草為界分塊的進行建圖分析。每當遇到了小草就到做是行或者是列到頭了。
這樣一來就是普通的二分圖了。
T_T這一題的數據是25*25是上限 。由於,最壞情況下是草和泥土相間出現。
還有就是以後做題的時候。特別是矩陣輸入一定要註意輸入行列問題!
!!
。!
!!!!
說多了都是淚啊。。。!
/* 把對行列覆蓋的木板當作點,則每一個格子變成了邊, 則問題轉換成了最小頂點覆蓋問題 */ #include <iostream> #include <algorithm> #include <vector> #include <cstdio> #include <cstring> using namespace std; const int MAXN = 50 + 10; const int MAXV = 1500; vector<int> G[MAXV]; char mp[MAXN][MAXN]; int numx[MAXN][MAXN],numy[MAXN][MAXN]; int match[MAXV]; bool used[MAXV]; int N,M,V; void init(){ for(int i = 0;i <= N*M;++i) G[i].clear(); } bool dfs(int u){ for(int i = 0;i < (int)G[u].size();++i){ int v = G[u][i]; if(!used[v]){ used[v] = 1; if(match[v] == -1||dfs(match[v])){ match[v] = u; return true; } } } return false; } void solve(){ int res = 0; memset(match,-1,sizeof(match)); for(int i = 1;i <= V;++i){ memset(used,0,sizeof(used)); if(dfs(i)) res++; } printf("%d\n",res); } int main() { // freopen("Input.txt","r",stdin); while(~scanf("%d%d",&N,&M)){ init(); for(int i = 0;i < N;++i){ scanf("%s",mp[i]); } int cnt = 0; memset(numx,0,sizeof(numx)); memset(numy,0,sizeof(numy)); for(int i = 0;i < N;++i) for(int j = 0;j < M;++j) if(mp[i][j] == '*'){ ++cnt; while(j < M&&mp[i][j] == '*'){ numx[i][j] = cnt; ++j; } } V = cnt; for(int j = 0;j < M;++j) for(int i = 0;i < N;++i) if(mp[i][j] == '*'){ ++cnt; while(i < N&&mp[i][j] == '*'){ numy[i][j] = cnt; ++i; } } for(int i = 0;i < N;++i){ for(int j = 0;j < M;++j){ if(numx[i][j] && numy[i][j]){ G[numx[i][j]].push_back(numy[i][j]); } } } solve(); } return 0; }
poj Muddy Fields