• pku3020 Antenna Placement (解法1)


    题解:在一个n*m的棋盘上,有一些标志,问最少用多少个1*2的矩形可以把它们全部套住。 
    可以将每一个标志与其相邻的四个标志建一条边,这样就形成了一个无向图,题目的意思即要求最小的边数。使得所有的点都在这些边数。
    这样就转换成了最小路径覆盖问题。
    最小路径覆盖=顶点数-最大二分匹配
    本题是无向图,即二分图中的边是双向边,若1和2匹配的话,那么2和1也匹配,
    所以本题=顶点数-最大二分匹配/2
     1 #include<iostream>
    2 using namespace std;
    3 const int Row=45;
    4 const int Line=15;
    5 char str[Row][Line];
    6 bool cover[Row][Line];
    7 char dir[4][2] = {1, 0, -1, 0, 0, 1, 0, -1} ;
    8 int h,w,cnt;
    9 struct Link
    10 {
    11 int x,y;
    12 }link[Row][Line];
    13 bool find (int py, int px)
    14 {
    15 int i, j ;
    16 int x, y ;
    17 for (i = 0 ; i < 4 ; ++i)
    18 {
    19 y = py + dir[i][0] ;
    20 x = px + dir[i][1] ;
    21 if ((0<x && x <=w && 0<y && y<=h) && !cover[y][x] && (str[y][x]=='*'))
    22 {
    23 cover[y][x] = true ;
    24 if (!link[y][x].x || find (link[y][x].y, link[y][x].x))
    25 {
    26 link[y][x].y = py ;
    27 link[y][x].x = px ;
    28 return 1 ;
    29 }
    30 }
    31 }
    32 return 0 ;
    33 }
    34
    35
    36
    37 int mach()
    38 {
    39 int sum=0;
    40 for (int j = 1 ; j <=h ; ++j)
    41 for (int i = 1 ; i <=w ; ++i)
    42 {
    43 if (str[j][i] == '*')
    44 {
    45 ++cnt ;
    46 memset (cover, false, sizeof (cover)) ;
    47 sum += find (j, i) ;
    48 }
    49 }
    50 return cnt-sum/2;
    51 }
    52
    53 int main()
    54 {
    55 int k;
    56 scanf("%d",&k);
    57
    58 while(k--)
    59 {
    60 cnt=0;
    61 scanf("%d %d",&h,&w);
    62 memset(link,0,sizeof(link));
    63 for(int i=1;i<=h;i++)
    64 {
    65 scanf("%s",&str[i][1]);
    66 }
    67 printf("%d\n",mach());
    68 }
    69
    70 return 0;
    71 }


     1 #include<iostream>
    2 using namespace std;
    3 const int Row=45;
    4 const int Line=15;
    5 char str[Row][Line];
    6 bool cover[Row][Line];
    7 char dir[4][2] = {1, 0, -1, 0, 0, 1, 0, -1} ;
    8 int h,w,cnt;
    9 struct Link
    10 {
    11 int x,y;
    12 }link[Row][Line];
    13 bool find (int py, int px)
    14 {
    15 int i, j ;
    16 int x, y ;
    17 for (i = 0 ; i < 4 ; ++i)
    18 {
    19 y = py + dir[i][0] ;
    20 x = px + dir[i][1] ;
    21 if ((0<x && x <=w && 0<y && y<=h) && !cover[y][x] && (str[y][x]=='*'))
    22 {
    23 cover[y][x] = true ;
    24 if (!link[y][x].x || find (link[y][x].y, link[y][x].x))
    25 {
    26 link[y][x].y = py ;
    27 link[y][x].x = px ;
    28 return 1 ;
    29 }
    30 }
    31 }
    32 return 0 ;
    33 }
    34
    35
    36
    37 int mach()
    38 {
    39 int sum=0;
    40 for (int j = 1 ; j <=h ; ++j)
    41 for (int i = 1 ; i <=w ; ++i)
    42 {
    43 if (str[j][i] == '*')
    44 {
    45 ++cnt ;
    46 memset (cover, false, sizeof (cover)) ;
    47 sum += find (j, i) ;
    48 }
    49 }
    50 return cnt-sum/2;
    51 }
    52
    53 int main()
    54 {
    55 int k;
    56 scanf("%d",&k);
    57
    58 while(k--)
    59 {
    60 cnt=0;
    61 scanf("%d %d",&h,&w);
    62 memset(link,0,sizeof(link));
    63 for(int i=1;i<=h;i++)
    64 {
    65 scanf("%s",&str[i][1]);
    66 }
    67 printf("%d\n",mach());
    68 }
    69
    70 return 0;
    71 }
     
    第二种解法将在近期公布。
  • 相关阅读:
    反射
    IDEA配置数据库
    配置idea的maven镜像为aliyun
    蓝桥---芯片测试(思维)
    汉诺塔(思维、DP思想)
    立方数(质因子、优化)
    碎碎念(DP)
    牛牛战队的比赛地(三分)
    子段乘积(尺取、逆元)
    子段异或(位运算)
  • 原文地址:https://www.cnblogs.com/tiankonguse/p/2403068.html
Copyright © 2020-2023  润新知