zoukankan      html  css  js  c++  java
  • 洛谷 P2825 [HEOI2016]游戏

    题目描述

    在2016年,佳缘姐姐喜欢上了一款游戏,叫做泡泡堂。简单的说,这个游戏就是在一张地图上放上若干个炸弹,看是否能炸到对手,或者躲开对手的炸弹。在玩游戏的过程中,小H想到了这样一个问题:当给定一张地图,在这张地图上最多能放上多少个炸弹能使得任意两个炸弹之间不会互相炸到。炸弹能炸到的范围是该炸弹所在的一行和一列,炸弹的威力可以穿透软石头,但是不能穿透硬石头。给定一张n*m的网格地图:其中*代表空地,炸弹的威力可以穿透,可以在空地上放置一枚炸弹。x代表软石头,炸弹的威力可以穿透,不能在此放置炸弹。#代表硬石头,炸弹的威力是不能穿透的,不能在此放置炸弹。例如:给出1*4的网格地图*xx*,这个地图上最多只能放置一个炸弹。给出另一个1*4的网格地图*x#*,这个地图最多能放置两个炸弹。现在小H任意给出一张n*m的网格地图,问你最多能放置多少炸弹。

    输入输出格式

    输入格式:

    第一行输入两个正整数n,m,n表示地图的行数,m表示地图的列数。1≤n,m≤50。接下来输入n行m列个字符,代表网格地图。*的个数不超过n*m个。

    输出格式:

    输出一个整数a,表示最多能放置炸弹的个数

    输入输出样例

    输入样例#1:
    4 4
    #∗∗∗
    ∗#∗∗
    ∗∗#∗
    xxx#
    输出样例#1:

     5

    套路题

    行和列构成二分图,把所有的*作为边,跑匹配

    问题在于这个构图比较麻烦,#会把一行/列分成两个

    可以预先把每个格子所在的行和列的编号处理出来

    注意最多会有1250*2+2个点

      1 #include <iostream>
      2 #include <cstdlib>
      3 #include <cstdio>
      4 #include <algorithm>
      5 #include <string>
      6 #include <cstring>
      7 #include <cmath>
      8 #include <map>
      9 #include <stack>
     10 #include <set>
     11 #include <vector>
     12 #include <queue>
     13 #include <time.h>
     14 #define eps 1e-7
     15 #define INF 0x3f3f3f3f
     16 #define MOD 1000000007
     17 #define rep0(j,n) for(int j=0;j<n;++j)
     18 #define rep1(j,n) for(int j=1;j<=n;++j)
     19 #define pb push_back
     20 #define set0(n) memset(n,0,sizeof(n))
     21 #define ll long long
     22 #define ull unsigned long long
     23 #define iter(i,v) for(edge *i=head[v];i;i=i->nxt)
     24 #define max(a,b) (a>b?a:b)
     25 #define min(a,b) (a<b?a:b)
     26 #define print_runtime printf("Running time:%.3lfs
    ",double(clock())/1000.0)
     27 #define TO(j) printf(#j": %d
    ",j);
     28 //#define OJ
     29 using namespace std;
     30 const int MAXINT = 100010;
     31 const int MAXNODE = 3000;
     32 const int MAXEDGE = 10000;
     33 char BUF,*buf;
     34 int read(){
     35     char c=getchar();int f=1,x=0;
     36     while(!isdigit(c)){if(c=='-') f=-1;c=getchar();}
     37     while(isdigit(c)){x=x*10+c-'0';c=getchar();}
     38     return f*x;
     39 }
     40 char get_ch(){
     41     char c=getchar();
     42     while(!isalpha(c)) c=getchar();
     43     return c;
     44 }
     45 //------------------- Head Files ----------------------//
     46 
     47 int n,m,cnt,q[MAXNODE],dis[MAXNODE],SS=MAXNODE-2,TT=MAXNODE-1,id_h[51][51],id_v[51][51],cnt_h,cnt_v;
     48 char mat[51][51];
     49 struct edge{
     50     int u,v,c;
     51     edge *nxt;
     52     edge(int _u,int _v,int _c,edge * _nxt):u(_u),v(_v),c(_c),nxt(_nxt){}
     53     edge(){}
     54 }mp[MAXEDGE],*head[MAXNODE];
     55 void addedge(int u,int v,int c){
     56     mp[cnt] = edge(u,v,c,head[u]);
     57     head[u] = &mp[cnt++];
     58     mp[cnt] = edge(v,u,0,head[v]);
     59     head[v] = &mp[cnt++];
     60 }
     61 edge *rev(edge *e){
     62     return &mp[(e-mp)^1];
     63 }
     64 int bfs(int ss,int tt){
     65     memset(dis,-1,sizeof(dis));
     66     int *h,*t,p;
     67     h=t=q;
     68     dis[ss]=0;
     69     *t++=ss;
     70     while(h!=t){
     71         p=*h++;
     72         iter(i,p){
     73             if(i->c&&dis[i->v]==-1){
     74                 dis[i->v]=dis[p]+1;
     75                 *t++=i->v;
     76             }
     77         }
     78     }
     79     return dis[tt]!=-1;
     80 }
     81 int dfs(int u,int v,int flow){
     82     int tmp,flow_t=0;
     83     if(u==v) return flow;
     84     iter(i,u){
     85         if(i->c&&dis[i->v]==dis[u]+1&&(tmp=dfs(i->v,v,min(i->c,flow-flow_t)))){
     86             flow_t+=tmp;
     87             i->c-=tmp;
     88             rev(i)->c+=tmp;
     89         }
     90     }
     91     if(flow_t==0) dis[u]=-1;
     92     return flow_t;
     93 }
     94 int dinic(int ss,int tt){
     95     int ans=0,tmp;
     96     while(bfs(ss,tt)){
     97         while(tmp=dfs(ss,tt,INF)) ans+=tmp;
     98     }
     99     return ans;
    100 }
    101 void get_input();
    102 void work();
    103 int main() {
    104     get_input();
    105     work();
    106     return 0;
    107 }
    108 void work(){
    109     rep0(i,n){
    110         rep0(j,m){
    111             if(mat[i][j]=='*') id_h[i][j]=cnt_h;
    112             if(mat[i][j]=='#') cnt_h++;
    113         }
    114         cnt_h++;
    115     }
    116     rep0(i,m){
    117         rep0(j,n){
    118             if(mat[j][i]=='*') id_v[j][i]=cnt_v;
    119             if(mat[j][i]=='#') cnt_v++;
    120         }
    121         cnt_v++;
    122     }
    123     rep0(i,cnt_h) addedge(SS,i,1);
    124     rep0(i,cnt_v) addedge(i+cnt_h,TT,1);
    125     rep0(i,n){
    126         rep0(j,m){
    127             if(mat[i][j]=='*') addedge(id_h[i][j],id_v[i][j]+cnt_h,1);
    128         }
    129     }
    130     printf("%d
    ",dinic(SS,TT));
    131 }
    132 void get_input(){
    133     n=read();m=read();
    134     rep0(i,n){
    135         scanf("%s",mat[i]);
    136     }
    137 }
    138 /*
    139 4 5
    140 *****
    141 #*#*#
    142 *****
    143 #*#*#
    144 */
  • 相关阅读:
    Sqlite教程(1) SQLiteOpenHelper
    检查网络连接状态。
    GSON解译Json为DTO
    Okhttp教程 (1)
    HashMap的扩容算法
    回溯算法
    动态规划
    实现自旋锁
    Java堆
    垃圾回收算法总结
  • 原文地址:https://www.cnblogs.com/LoveYayoi/p/6924078.html
Copyright © 2011-2022 走看看