HDU1045Fire Net (二分图|DFS)

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

猜你喜欢

转载自blog.csdn.net/nka_kun/article/details/79908270