题目:在n*n的方格里,放入几个喷火器,他们会攻击同行、同列的点,问做多能放多少个。
分析:图论,搜索,二分图匹配。本题可以利用搜索求解,这里我使用的是二分图匹配。
建图,把原图每行每列的不同的连续区间分别看成一个新图中的点xi与yj;
则边<xi,yj>表示原图中对应位置的点,原图中可以互相攻击的点就对应到新图中相同的xi与yj;
则新图中的二分图最大匹配即为,原图中不能相互攻击的最大摆放数量。
说明:图论关键就是建图。
#include <iostream> #include <cstdlib> #include <cstring> #include <cstdio> using namespace std; char maps[5][5]; int g[17][17]; int line[5][5],row[5][5]; int used[17],link[17]; int dfs(int s, int n) { for (int i = 0 ; i <= n ; ++ i) if (g[s][i] && !used[i]) { used[i] = 1; if (link[i] == -1 || dfs(link[i], n)) { link[i] = s; return 1; } } return 0; } int main() { int n,x,y; while (~scanf("%d",&n) && n) { for (int i = 0 ; i < n ; ++ i) scanf("%s",maps[i]); memset(line, -1, sizeof(line)); memset(row, -1, sizeof(row)); int line_count = -1,row_count = -1; for (int i = 0 ; i < n ; ++ i) for (int j = 0 ; j < n ; ++ j) { if (j == 0 || maps[i][j] != '.') line_count ++; if (maps[i][j] == '.') line[i][j] = line_count; if (j == 0 || maps[j][i] != '.') row_count ++; if (maps[j][i] == '.') row[j][i] = row_count; } memset(g, 0, sizeof(g)); for (int i = 0 ; i < n ; ++ i) for (int j = 0 ; j < n ; ++ j) if (maps[i][j] == '.') g[line[i][j]][row[i][j]] = 1; int sum = 0; memset(link, -1 ,sizeof(link)); for(int i = 0 ; i <= line_count ; ++ i) { memset(used, 0, sizeof(used)); sum += dfs(i, row_count); } printf("%d\n",sum); } return 0; }
UVa 639 - Don't Get Rooked
时间: 2024-12-21 18:10:57