Time Limit: 3000/1000MS (Java/Others)
Memory Limit: 65535/65535KB (Java/Others)
给出一个
n∗m
的矩形仓库,仓库里有的位置已经被占用,剩下的位置可以用来放东西。
问这个仓库还可以放下多少个
1∗2
或者
2∗1
的箱子。
Input
输入有多组数据。
每组数据,第一行为两个整数n,m。
从第二行开始为一个
n∗m
的矩形’.’表示为空,’*’表示已被占用。
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;
}