POJ 2226 Muddy Fields 二分图(难点在于建图)
题意:给定一个矩阵和它的N行M列,其中有一些地方有水,现在有一些长度任意,宽为1的木板,要求在板不跨越草,用一些木板盖住这些有水的地方,问至少需要几块板子?
思路:首先想到如果没有不准跨越草的条件则跟POJ 3041题意一样(如果想看的话可以点击这里),然而这一题多了个条件,那么将矩阵转化的方式需要改变,不能直接将行列分成两个集合了。需要先查看两遍矩阵,一遍横向查看有无连续‘*’的情况,若连续说明一块板子就可以覆盖,所以标记为同样的数字,反之则不同;同理另一遍纵向查看矩阵连续'*'的情况,处理方式同上。这样就建图完毕了。
1 #include<cstdio> 2 3 #include<cstring> 4 5 #include<iostream> 6 7 #include<algorithm> 8 9 using namespace std; 10 11 12 13 const int N = 600; 14 15 int n, m, p, q; 16 17 bool lin[N][N]; 18 19 int used[N], arr[N], mark[N][N]; 20 21 char map[N][N]; 22 23 24 25 bool find(int x) 26 27 { 28 29 for(int j = 1; j <= q; j++) 30 31 { 32 33 if(lin[x][j] && used[j] == 0) 34 35 { 36 37 used[j] = 1; 38 39 if(arr[j] == 0 || find(arr[j])) 40 41 { 42 43 arr[j] = x; 44 45 return true; 46 47 } 48 49 } 50 51 } 52 53 return false; 54 55 } 56 57 58 59 int main() 60 61 { 62 63 int r, c; 64 65 while(~scanf("%d%d", &n, &m)) 66 67 { 68 69 memset(map, '0', sizeof(map)); 70 71 for(int i = 0; i < n; i++) 72 73 { 74 75 scanf("%s", &map[i]); 76 77 } 78 79 memset(lin, false , sizeof(lin)); 80 81 memset(arr, 0, sizeof(arr)); 82 83 p = 0; 84 85 for(int i = 0; i < n; i++) 86 87 { 88 89 for(int j = 0; j < m; j++) 90 91 { 92 93 if(map[i][j] == '*') 94 95 { 96 97 if(map[i][j-1] != '*')//横向查看 98 99 { 100 101 p++; 102 103 } 104 105 mark[i][j] = p; 106 107 } 108 109 } 110 111 } 112 113 q = 0; 114 115 for(int j = 0; j < m; j++) 116 117 { 118 119 for(int i = 0; i < n; i++) 120 121 { 122 123 if(map[i][j] == '*') 124 125 { 126 127 if(map[i-1][j] != '*')//纵向查看 128 129 { 130 131 q++; 132 133 } 134 135 lin[mark[i][j]][q] = true;//横向已经检查完了可以直接建图了 136 137 } 138 139 } 140 141 } 142 143 int all = 0; 144 145 for(int i = 1; i <= p; i++) 146 147 { 148 149 memset(used, 0, sizeof(used)); 150 151 if(find(i)) 152 153 ++all; 154 155 } 156 157 printf("%d\n", all); 158 159 } 160 161 return 0; 162 163 }
适当比较,砥砺前行