Since time is limited, bomberman has to do this job quite efficiently. Now he has successfully defeated all the foes, and is searching for the exit. It's really troublesome to destroy the walls one by one, so he's asking for your help to calculate the minimal number of bombs he has to place in order to destroy all the walls, thus he can surely find the exit.
9 11 *********** *#.#...#.#* *.*.*.*.*.* *.........* *.*.*.*.*.* *....#....* *.*.*.*.*.* *....#....* *********** 3 13 ************* *..##...##..* *************
3 3
//
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define eps 1e-8
#define N 550
#define V 360000
int n,m;//n行 m列
int L[V],R[V];
int D[V],U[V];
int C[V];
int S[N],H[N];
int ak,size;//ak 最少多少行可以覆盖所有列(可重复)
void Link(int r,int c)
{
S[c]++;C[size]=c;
U[size]=U[c];D[U[c]]=size;
D[size]=c;U[c]=size;
if(H[r]==-1) H[r]=L[size]=R[size]=size;
else
{
L[size]=L[H[r]];R[L[H[r]]]=size;
R[size]=H[r];L[H[r]]=size;
}
size++;
}
void remove(int c)
{
int i;
for(i=D[c];i!=c;i=D[i])
L[R[i]]=L[i],R[L[i]]=R[i];
}
void resume(int c)
{
int i;
for(i=U[c];i!=c;i=U[i])
L[R[i]]=R[L[i]]=i;
}
int h()
{
int i,j,k,count=0;
bool visit[N];
memset(visit,0,sizeof(visit));
for(i=R[0];i;i=R[i])
{
if(visit[i]) continue;
count++;
visit[i]=1;
for(j=D[i];j!=i;j=D[j])
{
for(k=R[j];k!=j;k=R[k])
visit[C[k]]=1;
}
}
return count;
}
void Dance(int k)
{
int i,j,c,Min,ans;
ans=h();
if(k+ans>=ak) return;
if(!R[0])
{
if(k<ak) ak=k;
return;
}
for(Min=N,i=R[0];i;i=R[i])
if(S[i]<Min) Min=S[i],c=i;
for(i=D[c];i!=c;i=D[i])
{
remove(i);
for(j=R[i];j!=i;j=R[j])
remove(j);
Dance(k+1);
for(j=L[i];j!=i;j=L[j])
resume(j);
resume(i);
}
return;
}
char a[30][30];
int hash[30][30];
int mat[300][300];
int main()
{
int tn,tm;
while(scanf("%d%d",&tn,&tm)==2)
{
for(int i=0;i<tn;i++) scanf("%s",a[i]);
//每一个可以放炸弹的位置为行,所有可炸墙壁为列
n=m=0;
for(int i=0;i<tn;i++) for(int j=0;j<tm;j++)
if(a[i][j]=='#') hash[i][j]=++m;
memset(mat,0,sizeof(mat));
for(int i=0;i<tn;i++)
{
for(int j=0;j<tm;j++)
{
if(a[i][j]=='.')
{
++n;
for(int k=i-1;k>=0;k--)
{
if(a[k][j]=='#') {mat[n][hash[k][j]]=1;break;}
else if(a[k][j]=='*') break;//important
}
for(int k=i+1;k<tn;k++)
{
if(a[k][j]=='#') {mat[n][hash[k][j]]=1;break;}
else if(a[k][j]=='*') break;
}
for(int k=j-1;k>=0;k--)
{
if(a[i][k]=='#') {mat[n][hash[i][k]]=1;break;}
else if(a[i][k]=='*') break;
}
for(int k=j+1;k<tm;k++)
{
if(a[i][k]=='#') {mat[n][hash[i][k]]=1;break;}
else if(a[i][k]=='*') break;
}
}
}
}
//DLX
for(int i=0;i<=m;i++)
{
S[i]=0;
U[i]=D[i]=i;
L[i+1]=i;R[i]=i+1;
}R[m]=0;
memset(H,-1,sizeof(H));
size=m+1;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
if(mat[i][j]) Link(i,j);
}
}
ak=N;
Dance(0);
printf("%d\n",ak);
}
return 0;
}