【搜索模拟】

【搜索模拟】

搜索+大模拟

DFS模拟

像素放置

https://www.lanqiao.cn/problems/3508/learning/
注意搜索中的遍历方式
注意特别处理 x=1 和 y=1

/*
【结论】
当(x,y)被遍历到后,(x-1,y-1)已经确定->需要check
如果是最后一列:(x-1,y)也确定了 
*/
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
const int N=15;
char s[N][N];
int ans[N][N];
int n,m;
bool check(int x,int y){
	if(s[x][y]=='_') return true;
	int cnt=0;
	int res=s[x][y]-'0';
	for(int i=-1;i<=1;i++){
		for(int j=-1;j<=1;j++){
			int nx=x+i,ny=y+j;
			if(nx>=1 && nx<=n && ny>=1 && ny<=m){
				if(ans[nx][ny]) cnt++;
			}
		}
	}
	if(cnt==res) return true;
	else return false;
}
//设完回溯 
void dfs(int x,int y){
	//搜索出口:x搜完已经溢出 
	if(x==(n+1)){
		for(int i=1;i<=m;i++){
			if(!check(n,i)){
				return;
			}
		}
		for(int i=1;i<=n;i++){
			for(int j=1;j<=m;j++){
				cout<<ans[i][j];
			}
			cout<<endl;
		}
		return;
	}
	//换行
	if(y==m){
		ans[x][y]=1;
		//只有一列 
		if(x==1 || (y==1 && check(x-1,y)) || (check(x-1,y-1) && check(x-1,y))) dfs(x+1,1);
		ans[x][y]=0;
		if(x==1 || (y==1 && check(x-1,y)) || (check(x-1,y-1) && check(x-1,y))) dfs(x+1,1);
	}
	else{
		ans[x][y]=1;
		if(x==1 || y==1 || check(x-1,y-1)) dfs(x,y+1);
		ans[x][y]=0;
		if(x==1 || y==1 || check(x-1,y-1)) dfs(x,y+1);
	}
}
int main(){
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	cin>>n>>m;
	for(int i=1;i<=n;i++){
		for(int j=1;j<=m;j++){
			cin>>s[i][j];
		}
	}
	dfs(1,1);
	return 0;
}

新婚

https://ac.nowcoder.com/acm/contest/114593/E

题目大意

从根节点到每个叶节点的每条链,每个节点的值拼成一个二进制串,每个子串转为十进制,问每个数存不存在
注意到
f5623cfc-4209-4f0f-be54-69dffdaedc56

思路

dfs模拟一遍找链
因为数字的二进制位数最多为21 可以直接预处理出树上所有的*长度小于21*的链所代表的数字
dfs时用一个*栈*维护每个节点的数字

代码

const int N=1e5+10;
int n,q;
bool num[(1<<21)+10];
string s;
vector<int> g[N];
string t;//用栈维护子串
void dfs(int u,int fa){
    t.push_back(s[u-1]);
    int lb=max(0,(int)(t.size())-21);
    for(int i=t.size()-1;i>=lb;i--){
        string p=t.substr(i);//提取i到末尾的子串
        num[stoi(p,0,2)]=1;
        reverse(p.begin(),p.end());
        num[stoi(p,0,2)]=1;
    }
    for(auto son:g[u]){
        if(son!=fa){
            dfs(son,u);
        }
    }
    t.pop_back();//一条链找完了把子树出栈找另一个子树
}
void solve(){
    cin>>n>>q;
    cin>>s;
    for(int i=1;i<n;i++){
        int u,v;
        cin>>u>>v;
        g[u].push_back(v);
        g[v].push_back(u);
    }
    dfs(1,-1);
    while(q--){
        int x;
        cin>>x;
        if(num[x]) cout<<"YES"<<endl;
        else cout<<"NO"<<endl;
    }
}

BFS模拟

推箱子

注意代码细节:
(1)回溯路径
(2)记录路径移动的简洁性

https://ac.nowcoder.com/acm/contest/108301/I

题目大意

image

思路

不要傻傻的存状态模拟!
分析一下题目,有显然结论:
(1)一个连通区域:目标数和箱子数一定是一样
(2)一个箱子路过一个箱子:可以视为推新的箱子->可以视为经过
image

代码

const int N=55;
int n,m;
string s[N];
//路径回溯
int dist[N][N];
PII pre[N][N];
//目标位置
int px=-1,py=-1;
vector<pair<PII,PII>> ans;
//临时记路径
vector<PII> path;
char dir(PII x,PII y){
    if(y.fi==x.fi+1) return 'D';
    else if(y.fi==x.fi-1) return 'U';
    else if(y.sc==x.sc+1) return 'R';
    else if(y.sc==x.sc-1) return 'L';
    assert(0);
}
void bfs(int x,int y){
    memset(dist,0x3f,sizeof dist);
    queue<PII> q;
    q.push({x,y});
    dist[x][y]=0;
    px=-1;py=-1;
    path.clear();
    while(q.size()){
        auto t=q.front();
        q.pop();
        if(s[t.fi][t.sc]=='*'){
            px=t.fi;py=t.sc;
            int tx=px,ty=py;
            //回溯路线
            while(1){
                path.push_back({tx,ty});
                if(dist[tx][ty]==0) break;
                //更新要同时更新!
                tie(tx,ty)=pre[tx][ty];
            }
            return;
        }
        for(int k=0;k<4;k++){
            int nx=t.fi+dx[k],ny=t.sc+dy[k];
            if(nx<0 || nx>=n || ny<0 || ny>=m) continue;
            if(s[nx][ny]=='#') continue;
            if(dist[nx][ny]==inf_int){
                dist[nx][ny]=dist[t.fi][t.sc]+1;
                pre[nx][ny]=t;
                q.push({nx,ny});
            }
        }
    }
}
void path_save(){
    //一条路上不管! @ 那么如果路径上遇到了箱子要让箱子先推
    int now=0;
    int len_path=path.size();
    //注意这里终点不存:
    for(int i=1;i<len_path;i++){
        if(s[path[i].fi][path[i].sc]!='.'){
            //path是倒着存的:记录的时候要倒过来
            for(int j=i;j>now;j--){
                ans.push_back({path[j],path[j-1]});
            }
            now=i;
        }
    }
    //注意更新地图状态:原来的起始点设成空地,原来的目标点设成(!)
    s[path.back().fi][path.back().sc]='.';
    s[path[0].fi][path[0].sc]='!';
}
void solve(){
    cin>>n>>m;
    for(int i=0;i<n;i++) cin>>s[i];
    for(int i=0;i<n;i++){
        for(int j=0;j<m;j++){
            if(s[i][j]=='@'){
                bfs(i,j);
                if(px==-1){
                    cout<<-1<<endl;
                    return;
                }
                path_save();
            }
        }
    }
    cout<<ans.size()<<endl;
    for(auto [key,val]:ans){
        cout<<key.fi+1<<" "<<key.sc+1<<" "<<dir(key,val)<<endl;
    }
}
posted @ 2025-04-10 21:25  White_ink  阅读(10)  评论(0)    收藏  举报