• HDU 3360 National Treasures(最小点覆盖)


    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3360

    题目大意:

    在一个n*m的格子中,每个格子有一个数值,-1表示空,其余表示财宝。每个财宝的数值转换成二进制数,
    12个二进制位上数值,从右到左,第i个位是1表示图上相应第i序号位置需要有警卫。所有的要求位置有警卫财宝才安全。
    财宝可以被警卫替换。问至少需要替换多少财宝才能保证所有财宝的安全。

    解题思路:

    需要警戒位置是财宝的讯号对财宝位置讯号建边。由于警戒位置与财宝位置的横纵坐标奇偶相反,可以建得二分图。
    对于所建图,根据题意就是找出最少的顶点使得剩余顶点覆盖所有的边,即最小顶点覆盖数为答案。

    代码

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<vector>
     5 #include<queue>
     6 #include<algorithm>
     7 using namespace std;
     8 const int N=1e2+5;
     9 vector<int>v[N*N];
    10 
    11 int n,m,xN,yN;
    12 int link[N*N],num[N][N],mp[N][N];
    13 bool vis[N*N];
    14 int dir[][2] = {{-1,-2},{-2,-1},{-2,1},{-1,2},{1,2},{2,1},{2,-1},{1,-2},{-1,0},{0,1},{1,0},{0,-1}};
    15 
    16 bool dfs(int u){
    17     for(int i=0;i<v[u].size();i++){
    18         int t=v[u][i];
    19         if(!vis[t]){
    20             vis[t]=true;
    21             if(link[t]==-1||dfs(link[t])){
    22                 link[t]=u;
    23                 return true;
    24             }
    25         }
    26     }
    27     return false;
    28 }
    29 
    30 int max_match(){
    31     memset(link,-1,sizeof(link));
    32     int ans=0;
    33     for(int i=1;i<=xN;i++){
    34         memset(vis,false,sizeof(vis));
    35         if(dfs(i)) ans++;
    36     }
    37     return ans;
    38 }
    39 
    40 
    41 bool check(int x,int y){
    42     if(x<=0||y<=0||x>n||y>m||mp[x][y]==-1) return false;
    43     return true;
    44 }
    45 
    46  void init(){
    47     xN=yN=0;
    48     for(int i=0;i<=n*m;i++) v[i].clear();
    49  }
    50 
    51 int main(){
    52     int cas=0;
    53     while(~scanf("%d%d",&n,&m)&&n&&m){
    54         init();
    55         for(int i=1;i<=n;i++){
    56             for(int j=1;j<=m;j++){
    57                 if((i+j)%2==0) num[i][j]=++xN;
    58                 else num[i][j]=++yN;
    59             }
    60         }
    61         for(int i=1;i<=n;i++){
    62             for(int j=1;j<=m;j++){
    63                 scanf("%d",&mp[i][j]);
    64             }
    65         }
    66         for(int i=1;i<=n;i++){
    67             for(int j=1;j<=m;j++){
    68                 if(mp[i][j]==-1) continue;
    69                 for(int k=0;k<12;k++){
    70                     if(mp[i][j]&(1<<k)){
    71                         int x=i+dir[k][0];
    72                         int y=j+dir[k][1];
    73                         if(!check(x,y)) continue;
    74                         if((i+j)%2==0) v[num[i][j]].push_back(num[x][y]);
    75                         else v[num[x][y]].push_back(num[i][j]);
    76                     }
    77                 }
    78             }
    79         }
    80         printf("%d. %d
    ",++cas,max_match());
    81     }
    82     return 0;
    83 }
  • 相关阅读:
    第二周:对Java面向对象的特点的基本感受
    第一周学习情况
    插入排序
    快速排序
    vue传值(小demo)
    Vue下简单分页及搜索功能
    js超简单冒泡算法
    vue框架中实现今天昨天前天最近时间
    vue简单的v-for
    ssm web.xml配置解析
  • 原文地址:https://www.cnblogs.com/fu3638/p/8785231.html
Copyright © 2020-2023  润新知