标签:
http://poj.org/problem?id=3020
Time Limit: 1000MS | Memory Limit: 65536K | |
Total Submissions: 7565 | Accepted: 3758 |
Description
Input
Output
Sample Input
2 7 9 ooo**oooo **oo*ooo* o*oo**o** ooooooooo *******oo o*o*oo*oo *******oo 10 1 * * * o * * * * * *
Sample Output
17 5
详细请参考:
http://blog.csdn.net/ripwangh/article/details/47334941
题目大意:
给定一个地图,*代表城市,o代表空地,用天线来覆盖相邻的两个城市,问最少需要多少天线?(所谓相邻是指上下左右4个方向相邻)
最小路径覆盖问题,难点就是如何构图
假如是这个例子:
2
3 3
*oo
***
o*o
统计城市数量,并将其编号:
2
3 3
1oo
234
o5o
第一个城市编号1,天线可覆盖与它相邻的城市2,则1与2之间有一条连线也就是1与2匹配即G[1][2]= 1;
第二个城市编号2,天线可覆盖与它相邻的城市1,3;则G[2][1]=1,G[2][3]=1;
同理可得G[3][2]=1,G[3][4]=1,G[3][5]=1,G[4][3]=1,G[5][3]=1
将城市拆分成两部分分别存入集合X和集合Y中
X Y
1 1
2 2
3 3
4 4
5 5
构图后为:
X | 1 | 2 | 3 | 4 | 5 | |
Y | ||||||
1 | 0 | 1 | 0 | 0 | 0 | |
2 | 1 | 0 | 1 | 0 | 0 | |
3 | 0 | 1 | 0 | 1 | 1 | |
4 | 0 | 0 | 1 | 0 | 0 | |
5 | 0 | 0 | 1 | 0 | 0 |
最小路径覆盖 = 总点数 - 最大匹配数
由于将城市拆分成两份,所以求得的最大匹配应该除以2
#include<stdio.h> #include<queue> #include<string.h> #include<algorithm> #define INF 0x3f3f3f3f #define N 1010 using namespace std; int G[N][N], A[N][N], vis[N], used[N]; char maps[N][N]; int m, n, k, d[4][2] = {{0, 1}, {0, -1}, {1, 0}, {-1, 0}}; bool Find(int u)//求最大匹配 { int i; for(i = 1 ; i <= k ; i++) { if(!vis[i] && G[u][i]) { vis[i] = 1; if(!used[i] || Find(used[i])) { used[i] = u; return true; } } } return false; } void Build(int x, int y)//构图 { int a, b, i; for(i = 0 ; i < 4 ; i++)//无线会覆盖东南西北四个方向 { a = x + d[i][0]; b = y + d[i][1]; if(a >= 1 && a <= m && b >= 1 && b <= n) { G[A[x][y]][A[a][b]] = 1; G[A[a][b]][A[x][y]] = 1; } } } int main() { int t, i, j; scanf("%d", &t); while(t--) { scanf("%d%d", &m, &n); memset(G, 0, sizeof(G)); memset(A, 0, sizeof(A)); k = 1; for(i = 1 ; i <= m ; i++) { getchar(); for(j = 1 ; j <= n ; j++) { scanf("%c", &maps[i][j]); if(maps[i][j] == ‘*‘) { A[i][j] = k;//A[i][j]表示坐标为(i,j)这个城市的编号 k++; } } }//统计城市个数,并对其进行编号 k -= 1; for(i = 1 ; i <= m ; i++) { for(j = 1 ; j <= n ; j++) { if(A[i][j])//每找到一个城市便根据其对其四周进行构图 Build(i, j); } } int ans = 0; memset(used, 0, sizeof(used)); for(i = 1 ; i <= k ; i++) { memset(vis, 0, sizeof(vis)); if(Find(i)) ans++; } printf("%d\n", k - ans / 2); } return 0; } /* 2 3 3 *oo *** o*o */
poj 3020 Antenna Placement(最小路径覆盖 + 构图)
标签:
原文地址:http://www.cnblogs.com/qq2424260747/p/4727552.html