题意:一行一列本来只能放一个炸弹,除非有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的就不贴了,直接暴力放然后判断时候合法即可.