P5053 Clickbait 题解
天哪,看到这个题面,是不是瞬间不想做了?一看难度,居然是黄题。
其实我们可以模拟乱搞,将问题化为以下步骤解决:
- 扫描数组,获取每一个id,并获取其所在的块。
- 扫描数组,每找到一个合格的'-'就进行dfs找到连接的块。
- 以块1出发,进行递归,统计答案。
代码:
#include<bits/stdc++.h>
using namespace std;
const int N=2005;
#define DOT 0
#define LR 1
#define UD 2
#define CONER 3
#define NUMBER 4
int n,m,nmp[N][N];
bool coner[N][N];
char mp[N][N];
struct block{
int inid,sx,sy,ex,ey;
vector<int> outid;
}s[N];
const int dx[4]={0,0,-1,1},dy[4]={1,-1,0,0};
bool vis[N][N];
inline void reset(){memset(vis,false,sizeof vis);}
inline bool isnum(char ch){return ('0'<=ch&&ch<='9');}
inline bool valid(int x,int y){return (x>=1&&x<=n&&y>=1&&y<=m&&!vis[x][y]);}
int GetBlockId(int x,int y){
int res=0;
while(isnum(mp[x][y])&&valid(x,y)){
res*=10;res+=mp[x][y]-'0';
mp[x][y]='.';y++;
}
return res;
}
int sx=INT_MAX,sy=INT_MAX,ex,ey;
inline void resetget(){
sx=INT_MAX,sy=INT_MAX,ex=0,ey=0;
}
void GetBlock(int x,int y){
sx=min(sx,x),sy=min(sy,y),ex=max(ex,x),ey=max(ey,y);
vis[x][y]=1;
for(int i=0;i<4;i++){
int nx=x+dx[i],ny=y+dy[i];
if(valid(nx,ny)&&mp[nx][ny]=='.'){
GetBlock(nx,ny);
}
}
}
inline void afterget(int ownerid){
sx--,sy--,ex++,ey++;
for(int i=sx;i<=ex;i++){
for(int j=sy;j<=ey;j++){
nmp[i][j]=ownerid;vis[i][j]=1;
if((i==sx||i==ex)&&mp[i][j]=='+') coner[i][j]=1;
}
}
}
int GetConnection(int x,int y){
vis[x][y]=true;
for(int i=0;i<4;i++){
int nx=x+dx[i],ny=y+dy[i];
if(valid(nx,ny)&&mp[nx][ny]!='.'){
if(mp[x][y]=='-'&&mp[nx][ny]=='|') continue;
if(mp[x][y]=='|'&&mp[nx][ny]=='-'){
return nmp[nx][ny];
}
return GetConnection(nx,ny);
}
}
return -1;
}
vector<int> ans;
void GetAnswer(int x){
if(s[x].outid.empty()){
ans.push_back(x);
return;
}
for(int i=s[x].outid.size()-1;i>=0;i--){
GetAnswer(s[x].outid[i]);
}
ans.push_back(x);
return;
}
int main(){
cin>>n>>m;
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++) cin>>mp[i][j];
}
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
if(isnum(mp[i][j])){
int id=GetBlockId(i,j);
resetget();
GetBlock(i,j);
afterget(id);
vector<int> tmp;
s[id]={0,sx,sy,ex,ey,tmp};
}
}
}
bool f=false;reset();
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
if(!f&&coner[i][j]) f=1;
else if(f&&coner[i][j]) f=0;
if(!f&&mp[i][j]=='-'&&!vis[i][j]){
int from=0;
if(mp[i][j+1]=='|') from=nmp[i][j+1];
else from=nmp[i][j-1];
if(from==0) continue;
int to=GetConnection(i,j);
if(to==-1) continue;
s[from].outid.push_back(to);
s[to].inid=from;
}
}
}
GetAnswer(1);
for(int i=0;i<ans.size();i++){
cout<<ans[i]<<endl;
}
return 0;
}
未解之谜
如果N开1005会RE最后一个点,开2005可以AC。
附注:本地windows不会RE,linux评测机会RE
本文来自博客园,作者:haozexu,转载请注明原文链接:https://www.cnblogs.com/haozexu/p/17488397.html

浙公网安备 33010602011771号