题意:一行一列本来只能放一个炸弹,除非有X隔开就可以放多个.问最多可以多少个.
思路:跟一行一列只能一个一样,可以用二分图解决.我们先给每行的X隔开的每一段编号,再给列上X隔开的每一段编号,建立二分图即可.
代码:
#include<bits/stdc++.h>
#define mem(a,b) memset(a,b,sizeof(a))
#define mod 1000000007
using namespace std;
typedef long long ll;
const int maxn = 1e5+5;
const double esp = 1e-7;
const int ff = 0x3f3f3f3f;
map<int,int>::iterator it;
struct node
{
int num;
int p,q;
int h;
}b[52],g[52];
int n;
int cntb,cntg;
char mp[52][52];
int re[52][52];
int yy[52];
int vis[52];
int find(int x)
{
for(int i = 1;i<= cntg;i++)
{
if(re[x][i]&&!vis[i])
{
vis[i] = 1;
if(!yy[i]||find(yy[i]))
{
yy[i] = x;
return 1;
}
}
}
return 0;
}
void init()
{
cntb = cntg = 0;
mem(mp,0);
mem(re,0);
mem(yy,0);
mem(b,0);
mem(g,0);
}
int main()
{
while(cin>>n&&n)
{
init();
for(int i = 1;i<= n;i++)
for(int j = 1;j<= n;j++)
cin>>mp[i][j];
for(int i = 1;i<= n;i++)
{
for(int j = 1;j<= n;j++)
{
if(mp[i][j]!= 'X')
{
b[++cntb].num = cntb;
b[cntb].h = i;
b[cntb].p = b[cntb].q = j;
for(j = j+1;j<= n;j++)
if(mp[i][j] == 'X')
break;
else
b[cntb].q++;
}
}
}
for(int i = 1;i<= n;i++)
{
for(int j = 1;j<= n;j++)
{
if(mp[j][i]!= 'X')
{
g[++cntg].num = cntg;
g[cntg].h = i;
g[cntg].p = g[cntg].q = j;
for(j = j+1;j<= n;j++)
if(mp[j][i] == 'X')
break;
else
g[cntg].q++;
}
}
}
for(int i = 1;i<= cntb;i++)
{
for(int j = 1;j<= cntg;j++)
{
if(b[i].h>= g[j].p&&b[i].h<= g[j].q)
re[i][j] = 1;
}
}
int ans = 0;
for(int i = 1;i<= cntb;i++)
{
mem(vis,0);
if(find(i))
ans++;
}
cout<<ans<<endl;
}
return 0;
}
DFS的就不贴了,直接暴力放然后判断时候合法即可.