可以直接dfs暴搜,也可以转化为二分图匹配问题
每一行连续的片段可以缩为一个点,列上连续的片段也是,因为连续的片段最多放一个点
就分为行片段,列片段两部分,他们的交点就是边,求最大匹配就是最多可以放的点
dfs暴搜代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<queue>
using namespace std;
typedef long long ll;
const int N=10;
char g[N][N];
int ans;
bool a[N][N];
int n;
void dfs(int i,int j,int d)
{
if(i==n)
{
ans=max(ans,d);
return;
}
int nj=(j+1)%n;
int ni=i;
if(nj==0) ni++;
if(!a[i][j]&&g[i][j]!='X')
{
bool vis[N][N];
memcpy(vis,a,sizeof(a));
for(int p=j+1;p<n&&g[i][p]!='X';p++)
a[i][p]=true;
for(int q=i+1;q<n&&g[q][j]!='X';q++)
a[q][j]=true;
dfs(ni,nj,d+1);
memcpy(a,vis,sizeof(a));
}
dfs(ni,nj,d);
}
int main()
{
while(~scanf("%d",&n)&&n)
{
for(int i=0;i<n;i++)
scanf("%s",g[i]);
memset(a,false,sizeof(a));
ans=0;
dfs(0,0,0);
printf("%d\n",ans);
}
return 0;
}
二分图匹配代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<queue>
using namespace std;
typedef long long ll;
const int N=100+10;
const int M=200+10;
struct Edge
{
int to,nxt;
}edge[M];
int tot,first[N];
void addedge(int u,int v)
{
edge[tot].to=v;
edge[tot].nxt=first[u];
first[u]=tot++;
}
void init()
{
tot=0;
memset(first,-1,sizeof(first));
}
int linker[N];
bool used[N];
int uN;
bool dfs(int u)
{
for(int i=first[u];i!=-1;i=edge[i].nxt)
{
int v=edge[i].to;
if(!used[v])
{
used[v]=true;
if(linker[v]==-1||dfs(linker[v]))
{
linker[v]=u;
return true;
}
}
}
return false;
}
int hungary()
{
int res=0;
memset(linker,-1,sizeof(linker));
for(int u=0;u<uN;u++)
{
memset(used,false,sizeof(used));
if(dfs(u)) res++;
}
return res;
}
char g[10][10];
int id[10][10];
int main()
{
int n;
while(~scanf("%d",&n)&&n)
{
init();
for(int i=0;i<n;i++)
scanf("%s",g[i]);
int cnt=0;
for(int i=0;i<n;i++)
{
int j=0;
while(j<n)
{
if(g[i][j]=='.')
{
while(g[i][j]=='.'&&j<n)
{
id[i][j]=cnt;
j++;
}
cnt++;
}
j++;
}
}
uN=cnt;
for(int i=0;i<n;i++)
{
int j=0;
while(j<n)
{
if(g[j][i]=='.')
{
while(g[j][i]=='.'&&j<n)
{
addedge(id[j][i],cnt);
j++;
}
cnt++;
}
j++;
}
}
printf("%d\n",hungary());
}
return 0;
}