[UESTC1432]放箱子

Time Limit: 3000/1000MS (Java/Others)
Memory Limit: 65535/65535KB (Java/Others)

给出一个 nm 的矩形仓库,仓库里有的位置已经被占用,剩下的位置可以用来放东西。
问这个仓库还可以放下多少个 12 或者 21 的箱子。

Input

输入有多组数据。

每组数据,第一行为两个整数n,m。
从第二行开始为一个 nm 的矩形’.’表示为空,’*’表示已被占用。
1<=n,m<=100
保证箱子总数不超过500。

Output

每组数据输出一行:包含一个整数最多能放下的箱子数.

Sample Input

4 4
*..*
.*..
....
**.*
4 3
...
.*.
**.
.*.

Sample Output

4
3

题解:
拆点最大流
因为会被计算两次,所以答案要除以2

#include<bits/stdc++.h>
#define LiangJiaJun main
#define S 50001
#define T 50002
#define INF 1999122700
using namespace std;
int n,m,h[50004],ne=1;
struct edge{
    int to,nt,w;
}e[200004];
char mp[104][104];
bool tap[104][104];
int dx[4]={0,1,0,-1},
    dy[4]={1,0,-1,0};
void INSERT(int u,int v,int w){
     e[++ne].to = v;
     e[ne].w = w;
     e[ne].nt = h[u];
     h[u] = ne;
}
void add(int u,int v,int w){
     INSERT(u,v,w);
     INSERT(v,u,0);
}
queue<int>q;
bool inq[50004];
int dis[50004];
bool bfs(){
     for(int i=0;i<=T;i++)dis[i]=-1;
     q.push(S);dis[S]=0;inq[S]=1;
     while(!q.empty()){
        int x=q.front();q.pop();
        for(int i=h[x];i;i=e[i].nt){
            if(e[i].w&&dis[e[i].to]==-1){
                dis[e[i].to]=dis[x]+1;
                if(!inq[e[i].to]){
                    inq[e[i].to]=1;
                    q.push(e[i].to);
                }
            }
        }
        inq[x]=0;
     }
     if(dis[T]==-1)return 0;
     return 1;
}
int dfs(int x,int f){
    if(x==T)return f;
    int w,used=0;
    for(int i=h[x];i;i=e[i].nt){
        if(e[i].w&&dis[e[i].to]==dis[x]+1){
            w=f-used;
            w=dfs(e[i].to,min(e[i].w,w));
            e[i].w-=w;
            e[i^1].w+=w;
            used+=w;if(used==f)return f;
        }
    }
    if(!used)dis[x]=-1;
    return used;
}
int w33ha(){
    ne=1;
    memset(h,0,sizeof(h));
    memset(tap,0,sizeof(tap));
    for(int i=1;i<=n;i++)scanf("%s",mp[i]+1);
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
            if(mp[i][j]=='*')tap[i][j]=0;
            else tap[i][j]=1;
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            if(!tap[i][j])continue;
            add(S,(i-1)*m+j,1);
            add((i-1)*m+j+n*m,T,1);
            for(int k=0;k<4;k++){
                int nowx=i+dx[k],nowy=j+dy[k];
                if(nowx<=0||nowx>n||nowy<=0||nowy>m||(!tap[nowx][nowy]))continue;
                add((i-1)*m+j,(nowx-1)*m+nowy+n*m,1);
            }
        }
    }
    int ans=0;
    while(bfs())ans+=dfs(S,INF);

    printf("%d\n",ans/2);
    return 0;
}
int LiangJiaJun(){
    while(scanf("%d%d",&n,&m)!=EOF)w33ha();
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值