Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 1007 Accepted Submission(s): 353
题解:题意就是让找在这个矩阵中可以放的船最大数目;其中船之间可以有冰山,船间没冰山时船不能在同行同列;这样需要建图,先扫描行,如果遇到冰山t++;下一个数字可以继续匹配,下一行了t++,同样,再扫描列;得到二分匹配的x分部和y分部;
代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<vector>
using namespace std;
const int INF=0x3f3f3f3f;
const double PI=acos(-1.0);
#define mem(x,y) memset(x,y,sizeof(x))
typedef long long LL;
#define SI(x) scanf("%d",&x)
#define SL(x) scanf("%lld",&x)
#define T_T while(T--)
#define F(i,x) for(i=0;i<x;i++)
#define PR(x) printf("%d",x)
#define PL(x) printf("%lld",x)
#define p_ printf(" ")
const int MAXN=1010;
char s[MAXN][MAXN];
int mp[MAXN][MAXN],vis[MAXN],link[MAXN],x[110][110],y[110][110];
int m,n,t1,t2;
int getmpxy(int rl,int a[][110]){//扫描行和列得到二分匹配的x部和y部
int t=0,i,j;
if(rl)F(i,m){
F(j,n){
if(s[i][j]==‘*‘)a[i][j]=t;
if(s[i][j]==‘#‘)t++;
}
t++;
}
else F(j,n){
F(i,m){
if(s[i][j]==‘*‘)a[i][j]=t;
if(s[i][j]==‘#‘)t++;
}
t++;
}
return t;
}
void getmp(){
mem(x,0);mem(y,0);
t1=getmpxy(1,x);
t2=getmpxy(0,y);
int i,j;
F(i,m){
F(j,n){
if(s[i][j]==‘*‘){
// printf("%d %d\n",x[i][j],y[i][j]);
mp[x[i][j]][y[i][j]]=1;
}
}
}
}
bool dfs(int x){
int i,j;
F(i,t2){
if(!vis[i]&&mp[x][i]){
vis[i]=1;
if(link[i]==-1||dfs(link[i])){//||
link[i]=x;
return true;
}
}
}
return false;
}
int km(){
mem(link,-1);
int i,j;
int ans=0;
F(i,t1){
mem(vis,0);
if(dfs(i))ans++;
}
return ans;
}
int main(){
int T;
SI(T);
T_T{
SI(m);SI(n);
int i,j;
mem(mp,0);
F(i,m)
scanf("%s",s[i]);
getmp();
PR(km());
puts("");
}
return 0;
}
原文:http://www.cnblogs.com/handsomecui/p/4998906.html