zoukankan      html  css  js  c++  java
  • 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 }
  • 相关阅读:
    sqlserver中判断表或临时表是否存在
    Delphi 简单方法搜索定位TreeView项
    hdu 2010 水仙花数
    hdu 1061 Rightmost Digit
    hdu 2041 超级楼梯
    hdu 2012 素数判定
    hdu 1425 sort
    hdu 1071 The area
    hdu 1005 Number Sequence
    hdu 1021 Fibonacci Again
  • 原文地址:https://www.cnblogs.com/fu3638/p/8785231.html
Copyright © 2011-2022 走看看