2 4 4 *ooo o### **#* ooo* 4 4 #*** *#** **#* ooo#
3 5
将一片最多只能放一个船的连续网格叫做‘块’。
以样例一为例
首先只考虑行,将每个块标号:将答案存入x [ ] [ ]
1000
0000
2203
0004
再此只考虑列,将每个块标号:将答案存入y [ ][ ]
1000
0000
2304
0004
void getmap(){ for(int i = 0; i < n; ++i){ for(int j = 0; j < m; ++j) if(str[i][j] == '*') map[x[i][j]][y[i][j]] = 1; } return ; }
所以将行块看做一个集合,列块看做一个集合。
所求的最大放船数就是两个集合之间的最大匹配数。
#include <cstdio> #include <cstring> #include <algorithm> #define maxn 55 using namespace std; int map[maxn * 55][maxn * 55]; char str[maxn][maxn]; int used[maxn * 55]; int link[maxn * 55]; int x[maxn][maxn]; int y[maxn][maxn]; int n, m; int x1, y1; void init(){ memset(map, 0, sizeof(map)); memset(x, 0, sizeof(x)); memset(y, 0, sizeof(y)); } void input(){ scanf("%d%d", &n, &m); for(int i = 0; i < n; ++i) scanf("%s", str[i]); } void creat_x(){ x1 = 1; for(int i = 0; i < n; ++i){ for(int j = 0; j < m; ++j){ if(str[i][j] == '*') x[i][j] = x1; if(str[i][j] == '#') x1++; } x1++; } return ; } void creat_y(){ y1 = 1; for(int j = 0; j < m; ++j){ for(int i = 0; i < n; ++i){ if(str[i][j] == '*') y[i][j] = y1; if(str[i][j] == '#') y1++; } y1++; } return ; } void getmap(){ for(int i = 0; i < n; ++i){ for(int j = 0; j < m; ++j) if(str[i][j] == '*') map[x[i][j]][y[i][j]] = 1; } return ; } bool dfs(int x){ for(int i = 1; i < y1; ++i){ if(map[x][i] && !used[i]){ used[i] = 1; if(link[i] == -1 || dfs(link[i])){ link[i] = x; return true; } } } return false; } int hungary(){ int ans = 0; memset(link, -1, sizeof(link)); for(int j = 1; j < x1; ++j){ memset(used, 0, sizeof(used)); if(dfs(j)) ans++; } return ans; } int main (){ int T; scanf("%d", &T); while(T--){ init(); input(); creat_x(); // for(int i = 0; i < n; ++i){ // for(int j = 0; j < m; ++j) // printf("%d", x[i][j]); // printf("\n"); // } creat_y(); // for(int i = 0; i < n; ++i){ // for(int j = 0; j < m; ++j) // printf("%d", y[i][j]); // printf("\n"); // } //printf("--%d %d\n", x1,y1); getmap(); int sum = hungary(); printf("%d\n", sum); } return 0; }