P5053 Clickbait 题解

天哪,看到这个题面,是不是瞬间不想做了?一看难度,居然是黄题。

其实我们可以模拟乱搞,将问题化为以下步骤解决:

  1. 扫描数组,获取每一个id,并获取其所在的块。
  2. 扫描数组,每找到一个合格的'-'就进行dfs找到连接的块。
  3. 以块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

posted @ 2023-06-17 22:31  haozexu  阅读(17)  评论(0)    收藏  举报