题意:
模仿炸弹人游戏,本题中炸弹的威力无限(无阻碍时威力为一整列一整行),给出至大15*15的地图,问最少同时放置几个炸弹,可以将墙一下炸完。
思路:
对每个墙编号,遍历图求出把炸弹放在每个点可以炸的墙,然后舞蹈链可重复匹配
代码:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int inf=0x3f3f3f3f;
const ll INF=0x3f3f3f3f3f3f3f3fll;
const int maxn=230;
int L[maxn*maxn],R[maxn*maxn],U[maxn*maxn],D[maxn*maxn];//节点的上下左右四个方向的链表
int C[maxn*maxn],H[maxn],cnt[maxn],vis[maxn];//C列H行cnt列链表中元素个数
int n,m,id,fans,u,v,q,p,s,a[20][20],cut;
char mp[20][20];
set< set<int> >poi;
bool flag;
void init(){
for(int i=0;i<=cut;i++){
cnt[i]=0;U[i]=D[i]=i;
L[i+1]=i;R[i]=i+1;
}
R[cut]=0;id=cut+1;
memset(H,-1,sizeof(H));
}
void Link(int r,int c){
cnt[c]++;C[id]=c;
U[id]=U[c];D[U[c]]=id;
D[id]=c;U[c]=id;
if(H[r]==-1) H[r]=L[id]=R[id]=id;
else{
L[id]=L[H[r]];R[L[H[r]]]=id;
R[id]=H[r];L[H[r]]=id;
}
id++;
}
void Remove(int Size){
for(int j=D[Size];j!=Size;j=D[j])
L[R[j]]=L[j],R[L[j]]=R[j];
}
void Resume(int Size){
for(int j=D[Size];j!=Size;j=D[j])
L[R[j]]=R[L[j]]=j;
}
int h()
{
int sum=0;
memset(vis,0,sizeof(vis));
for(int i=R[0];i;i=R[i]){
if(vis[i]) continue;
sum++;
for(int j=D[i];j!=i;j=D[j]){
for(int k=R[j];k!=j;k=R[k])
vis[C[k]]=1;
}
}
return sum;
}
void Dance(int k){
int mm=maxn,pos;
if(k+h()>=fans) return;
if(!R[0]){
if(k<fans) fans=k;
return;
}
for(int i=R[0];i;i=R[i])
if(mm>cnt[i]) mm=cnt[i],pos=i;
for(int i=D[pos];i!=pos;i=D[i])
{
Remove(i);
for(int j=R[i];j!=i;j=R[j]) Remove(j);
Dance(k+1);
for(int j=R[i];j!=i;j=R[j]) Resume(j);
Resume(i);
}
}
void get(int x,int y){
set<int> al;
for(int i=x-1;i>0;i--){
if(a[i][y]==-1)
break;
else if(a[i][y]){
al.insert(a[i][y]);
break;
}
}
for(int i=x+1;i<n;i++){
if(a[i][y]==-1)
break;
else if(a[i][y]){
al.insert(a[i][y]);
break;
}
}
for(int i=y-1;i>0;i--){
if(a[x][i]==-1)
break;
else if(a[x][i]){
al.insert(a[x][i]);
break;
}
}
for(int i=y+1;i<m;i++){
if(a[x][i]==-1)
break;
else if(a[x][i]){
al.insert(a[x][i]);
break;
}
}
if(poi.find(al)==poi.end()){
s++;
poi.insert(al);
//cout<<s<<' '<<x<<' '<<y<<endl;
for(set <int>::iterator it=al.begin();it!=al.end();it++){
Link(s,*it);
//cout<<*it;
}
//cout<<endl;
}
}
int main(){
while(scanf("%d %d",&n,&m)!=-1){
getchar();
cut=0;
for(int i=0;i<n;i++)
gets(mp[i]);
for(int i=0;i<n;i++){
for(int j=0;j<m;j++){
if(mp[i][j]=='#')
a[i][j]=++cut;
else if(mp[i][j]=='*')
a[i][j]=-1;
else
a[i][j]=0;
}
//getchar();
}
init();
s=0;
poi.clear();
for(int i=1;i<n;i++){
for(int j=1;j<m;j++){
if(a[i][j]==0)
get(i,j);
}
}
fans=cut;
Dance(0);
printf("%d\n",fans);
}
return 0;
}
Bomberman has been a very popular game ever since it was released. As you can see above, the game is played in an N*M rectangular room. Bomberman can go around the room and place bombs. Bombs explode in 4 directions with radius r. To finish a stage, bomberman has to defeat all the foes with his bombs and find an exit behind one of the walls.
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.
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