題解 U22784 【yizimi的玄學炸彈人】
阿新 • • 發佈:2018-12-02
題目連結:https://www.luogu.org/problemnew/show/U22784
題目
題目背景
yizimi最近喜歡玩一個很玄學的炸彈人遊戲
題目描述
在一張n × m(2<n,m<=5000)的地圖上,‘#’表示牆,‘*’表示敵人,‘.’表示空地(可以通過或安放炸彈),給出yizimi所在的初始位置(startx,starty),他只可放一顆炸彈,炸彈威力極大,可以同時炸死同一列,同一行的敵人,不過不能穿牆(牆後的敵人炸不死(霧))。問他可以去哪裡放炸彈,使得炸死的敵人最多?最多多少?
注意:yizimi不可以往敵人身上撞喲!
感謝涼涼提供資料支援!!!
輸入輸出格式
輸入格式:
第一行:n , m , startx , starty。分別指地圖行數、列數、初始位置的座標 第2~n+1行:輸入m個字元,指地圖。
輸出格式:
第一行輸出座標,用空格空開 第二行輸出最多炸死的敵人
說明
20%資料滿足:2<n,m<=10
100%資料滿足:2<n,m<=5000
總滿足1<startx,starty<n
總滿足地圖最外層為牆
保證yizimi炸死最多的方案唯一(不限定做法)
不保證yizimi可以去到所有空地
題目分析
首先,這是一組迷宮題,別看資料很大,m,n都能到5000,實際上因為只求連通的面積中的大小,直接爆搜就可以了。
演算法精析
1.求一個點可以炸死多少敵人
其實就是上下左右四個方向,只要炸到牆,就停止。一個方向的程式碼如下:
x=i;y=j;//這句話千萬別忘了!!!否則就會算成其他行的敵人數
while(a[x][y]!='#'){
if(a[x--][y]=='*'){//向左的,其餘變變方向即可
sum++;
}
}
2.求連通
用一個DFS去求連通(BFS一樣OK啦),每次前進順便把結果計算一下。
void dfs(int x,int y){ int tx,ty,k,sum; sum=_num(x,y); if(sum>maxx){ maxx=sum; mx=x; my=y; } for(k=1;k<=4;k++){ tx=x+next[k][0]; ty=y+next[k][1]; if(tx<1 || tx>n || ty<1 || ty>m ){ continue; } if(a[tx][ty]=='.' && !book[tx][ty]){ book[tx][ty]=1; dfs(tx,ty); } } return; }
完整程式碼
有我自己的程式碼習慣,勿噴
和上面程式碼有些不同,其實等效
#include<iostream>
#include<string>
#include<iostream>
using namespace std;
#define go(i,j,n,k) for(register int i=j;i<=n;i+=k)
#define fo(i,j,n,k) for(register int i=j;i>=n;i-=k)
#define mn 5010
char a[mn][mn];
int book[mn][mn]={0};
int maxx,mx,my,n,m;
int next[5][2]={{0,0},{0,1},{1,0},{0,-1},{-1,0}};
inline int _num(int i,int j){
int sum=0,x,y;
x=i;y=j;
while(a[x][y]!='#')
if(a[x--][y]=='*')
sum++;
x=i;y=j;
while(a[x][y]!='#')
if(a[x++][y]=='*')
sum++;
x=i;y=j;
while(a[x][y]!='#')
if(a[x][y--]=='*')
sum++;
x=i;y=j;
while(a[x][y]!='#')
if(a[x][y++]=='*')
sum++;
return sum;
}
inline void dfs(int x,int y){
int tx,ty,k,sum;
sum=_num(x,y);
if(sum>maxx)
maxx=sum,mx=x,my=y;
go(k,1,4,1){
tx=x+next[k][0];
ty=y+next[k][1];
if(tx<1 || tx>n || ty<1 || ty>m )
continue;
if(a[tx][ty]=='.' && !book[tx][ty])
book[tx][ty]=1,dfs(tx,ty);
}
return;
}
int main(){
int i,j,startx,starty;
//freopen("yizimi001.in","r",stdin);
cin>>n>>m>>startx>>starty;
go(i,1,n,1)
go(j,1,m,1)
cin>>a[i][j];
book[startx][starty]=1;
maxx=_num(startx,starty);
mx=startx,my=starty;
dfs(startx,starty);
cout<<mx<<" "<<my<<"\n";
cout<<maxx;
return 0;
}