HDU 5093 Battle ships(最大流 or 二分匹配)

题目:Battle Ships

题意:给一个由‘#’,‘*’,‘o’三种字符组成的矩阵,要求选择一些‘*’来摆战舰,同一行或同一列的战舰如果中间没有‘#’隔开是会互相攻击的,所以没有‘#’隔开时不能同时放,‘o’上不能摆放,要求最多摆多少战舰。

将所有行拿出来重新编号,对于被‘#’隔成多行的,可以看做多行,设置一个源点,每个行看作一个点,源点到这些点都连一条边,流量为1。表示这些行可以放置一个。

同样道理取出所有列,设置一个汇点,每个列对应的点连一条流量为1的边到汇点,表示这些列可以放置一个。

然后对于所有的‘*’,找出它们对应的行和列,从行到列连一条边,表示在对应的行和列放置一个。

最后求一下最大流就是答案。

PS:也可以直接根据行和列构建二部图求最大匹配。

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
const int N = 3000;
const int M = 60;
const int inf = 0x7fffffff;
char map[M][M];
#define pb push_back
struct Edge{
    int from,to,cap,flow;
    Edge(){}
    Edge(int from,int to,int cap,int flow):from(from),to(to),cap(cap),flow(flow){}
};
vector<Edge> G;
vector<int> V[N];
void add(int from, int to, int cap){
    G.pb(Edge(from,to,cap,0));
    G.pb(Edge(to,from,0,0));
    int x=G.size();
    V[from].pb(x-2);
    V[to].pb(x-1);
}
int T, n, m, a, b, tar;
int id[M][M][2];
int sch(int x, int y, int d){
    if(map[x][y]=='#' || x<0 || y<0)    return ++b;
    if(d)   id[x][y][d] = sch(x-1, y, d);
    else    id[x][y][d] = sch(x, y-1, d);
    return id[x][y][d];
}
int cur[N], d[N];
bool bfs(){
    memset(d, -1, sizeof(d));
    queue<int> Q;
    Q.push(0);
    d[0] = 0;
    while(!Q.empty()){
        int x=Q.front(); Q.pop();
        for(int i=0; i<V[x].size(); i++){
            Edge &e = G[V[x][i]];
            if(d[e.to]==-1 && e.cap>e.flow){
                d[e.to] = d[x]+1;
                Q.push(e.to);
            }
        }
    }
    return d[tar]!=-1;
}
int dfs(int x, int v){
    if(x==tar || v==0)  return v;
    int flow=0, f;
    for(int &i=cur[x]; i<V[x].size(); i++){
        int j = V[x][i];
        Edge &e = G[j];
        if(d[e.to]==d[x]+1 && (f=dfs(e.to, min(v,e.cap-e.flow)))>0){
            flow += f;
            v -= f;
            e.flow += f;
            G[j^1].flow -= f;
            if(!v)  break;
        }
    }
    return flow;
}
int solve(){
    G.clear();
    for(int i=0; i<=tar; i++)   V[i].clear();
    for(int i=0; i<n; i++){
        for(int j=0; j<m; j++){
            if(map[i][j]=='*' && id[i][j][0]!=-1 && id[i][j][1]!=-1){
                add(id[i][j][0], id[i][j][1], 1);
            }
        }
    }
    for(int i=1; i<=a; i++) add(0, i, 1);
    for(int i=a+1; i<=b; i++)   add(i, tar, 1);
    int flow=0;
    while(bfs()){
        memset(cur, 0, sizeof(cur));
        flow += dfs(0, inf);
    }
    return flow;
}
int main(){
    scanf("%d", &T);
    while(T--){
        scanf("%d %d", &n, &m);
        b = 0;
        memset(id, -1, sizeof(id));
        for(int i=0; i<n; i++){
            scanf("%s", map[i]);
            for(int j=m-1; j>=0; j--){
                if(map[i][j]!='#' && id[i][j][0]==-1)   id[i][j][0] = sch(i, j, 0);
            }
        }
        a = b;
        for(int i=n-1; i>=0; i--){
            for(int j=0; j<m; j++){
                if(map[i][j]!='#' && id[i][j][1]==-1)   id[i][j][1] = sch(i, j, 1);
            }
        }
        tar = b+1;
        printf("%d\n", solve());
    }
    return 0;
}


1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值