您的位置:首页 > 其它

【Tjoi2016&Heoi2016】【BZOJ 4554】【JZOJ 4612】游戏

2016-07-12 14:10 399 查看

Description

在2016年,佳缘姐姐喜欢上了一款游戏,叫做泡泡堂。简单的说,这个游戏就是在一张地图上放上若干个炸弹,看

是否能炸到对手,或者躲开对手的炸弹。在玩游戏的过程中,小H想到了这样一个问题:当给定一张地图,在这张

地图上最多能放上多少个炸弹能使得任意两个炸弹之间不会互相炸到。炸弹能炸到的范围是该炸弹所在的一行和一

列,炸弹的威力可以穿透软石头,但是不能穿透硬石头。给定一张n*m的网格地图:其中*代表空地,炸弹的威力可

以穿透,可以在空地上放置一枚炸弹。x代表软石头,炸弹的威力可以穿透,不能在此放置炸弹。#代表硬石头,炸

弹的威力是不能穿透的,不能在此放置炸弹。例如:给出1*4的网格地图xx,这个地图上最多只能放置一个炸弹

。给出另一个1*4的网格地图x#,这个地图最多能放置两个炸弹。现在小H任意给出一张n*m的网格地图,问你最

多能放置多少炸弹

Solution

看起来像搜索或贪心,但实际是网络流二分图最大匹配,

先把整个矩阵的边缘打上#,

我们把每个*点视为左边的#与上边的#的一条边,因为每段没有阻挡的区间只允许一个炸弹,

最后用匈牙利算法做一遍二分图最大匹配即可

Code

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#define fo(i,a,b) for(int i=a;i<=b;i++)
#define H(i,j) ((i)*(m+1)+j)
#define link(q,w) b[q][++b[q][0]]=w
using namespace std;
const int N=55*55;
int n,m,ans,I;
int b

,zx
;
int z
;
char a[55][55];
bool OK(int q)
{
if(z[q]>=I)return 0;
z[q]=I;
fo(i,1,b[q][0])
{
if(!zx[b[q][i]]||OK(zx[b[q][i]])){zx[b[q][i]]=q;return 1;}
}
return 0;
}
int main()
{
scanf("%d%d",&n,&m);
fo(i,1,n)a[i][0]=a[0][i]='#';
fo(i,1,n)fo(j,1,m)
{
char ch=' ';
while(ch!='*'&&ch!='x'&&ch!='#')ch=getchar();
a[i][j]=ch;
if(ch=='*')
{
int I,J;
for(I=i-1;a[I][j]!='#';I--);
for(J=j-1;a[i][J]!='#';J--);
link(H(i,J),H(I,j));
}
}
I=0;
fo(i,1,n)fo(j,0,m)if(a[i][j]=='#')
{
I++;
if(OK(H(i,j)))ans++;
}
printf("%d\n",ans);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: