dfs

dfs

1.P2036

#include<bits/stdc++.h>
using namespace std;
typedef long long int ll;
int n;
ll s[12];
ll k[12];
ll ans=1e9;
void dfs(int dep,ll suan,ll ku,int cnt){
	
    if(dep==n+1){
    	if(cnt==0){//没有取配料,保证至少取一种配料
    		return;
		}
    	ll a= abs(suan-ku);
        ans=min(ans,a);
        return;
    }
    
//    cout<<"hi";
    dfs(dep+1,suan*s[dep],ku+k[dep],cnt+1);//当前配料取
    dfs(dep+1,suan,ku,cnt);//当前配料不取
}
int main(){
cin>>n;
for(int i=1;i<=n;i++){
    cin>>s[i]>>k[i];
}
    dfs(1,1,0,0);
    cout<<ans;
    return 0;
}
//这个题不适合动态规划

 2.P1605 迷宫

 

#include<bits/stdc++.h> 
using namespace std;
int n,m,t;
int ans;
int sx,sy,fx,fy;
int path[8][8];
bool st[8][8];//是否经过 
int dx[4]={-1,1,0,0};//上下左右 (行)
int dy[4]={0,0,-1,1};//(列)
void dfs(int x,int y){
	if(x==fx&&y==fy){
		ans++;
	}
	for(int i=0;i<4;i++){
		int bx=x+dx[i];
		int by=y+dy[i];
		if(st[bx][by]||bx<1||bx>n||by<1||by>m||path[bx][by]==1){
			continue;
		}
		st[bx][by]=true;
		dfs(bx,by);
		st[bx][by]=false;
	}
}
int main(){
cin>>n>>m>>t;//n行m列t个障碍
cin>>sx>>sy;//起点
cin>>fx>>fy;//终点
int x,y;
while(t--) {
	cin>>x>>y;
	path[x][y]=1;//1表示有障碍 
}
st[sx][sy]=true;
dfs(sx,sy);
cout<<ans;
	return 0;
}

注意:

易错点是起点一定是最开始就经过了,所以要true(防止后续再走,原题要求每个点最多只能走一次)

st[sx][sy]=true;

P2404 自然数的拆分

#include<bits/stdc++.h> 
using namespace std;
int n;
string ans;
void dfs(int s,int pre){//pre指的是上一位的数字,目的是要使得输出每一位递增(或相等)
	if(s==n){
		cout<<ans<<endl;
	}
	for(int i=1;i<n;i++){
	if(i<pre)continue;
	if(s+i>n)continue;
	pre=i;
	if(!ans.empty()){
		ans+='+';
		ans+=i+'0';
	}
	else{
		ans+=i+'0';
	}
		dfs(s+i,pre);
	if(ans.size()==1)	ans.erase(ans.size()-1,1);
	else{
			ans.erase(ans.size()-2,2);
	}
	}
}
int main(){
cin>>n;
dfs(0,0);	
	return 0;
}

P1101 单词方阵

#include<bits/stdc++.h> 
using namespace std;
//利用结构体数组记录yizhong所经历的位置 (存放多个变量的组合可以用结构体)
struct node{
int x;//行 
int y;//列 
}path[110];
//方向向量
int dx[8]={-1,-1,0,1,1,1,0,-1};//行
int dy[8]={0,1,1,1,0,-1,-1,-1};//列 
int n;
string s="yizhong";
const int N=110;
char g[N][N];//原字符串方阵 
bool vis[N][N];//是否在yizhong里
void dfs(int a,int b,int dep,int fx){
if(dep==7){//递归出口 
for(int i=0;i<7;i++){//yizhong路径上
vis[path[i].x][path[i].y]=true;
}
return; 
}
//下一个点 
int bx=a+dx[fx];
int by=b+dy[fx];
if(dep==6||g[bx][by]==s[dep+1]) {//下一个点必须是字符串里下一个,或者已经到yizhong的g
// vis[x][y]=true;要走完整个yizhong才可以确定整个路径上的字母是true的
//放入路径 
path[dep].x=a;
path[dep].y=b;
dfs(bx,by,dep+1,fx);
}
}
int main() {
cin>>n;
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
cin>>g[i][j];
}
}
//做dfs (每个点都要做,对每个点八个方向搜一遍)
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
if(g[i][j]=='y'){
//起点必须是y
//考虑选择哪一方向延伸,因为同一单词的摆放不能变方向
for(int k=0;k<8;k++) {
int x=i+dx[k];
int y=j+dy[k];
if(g[x][y]=='i'){//如果第二位是i,说明这个方向可能可以
dfs(i,j,0,k) ;//起点是(i,j)方向是沿着k然后进行dfs 
 
}
}
}
}
}
//输出答案
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
if(vis[i][j]){//如果在yizhong里面的话 
cout<<g[i][j];
}
else{
cout<<'*';
}
}
cout<<endl;
}
return 0;
}
 

完整代码

#include<bits/stdc++.h> 
using namespace std;
//利用结构体数组记录yizhong所经历的位置 
struct node{
	int x;//行 
	int y;//列 
}path[110];
//方向向量
int dx[8]={-1,-1,0,1,1,1,0,-1};//行
int dy[8]={0,1,1,1,0,-1,-1,-1};//列 
int n;
string s="yizhong";
const int N=110;
char g[N][N];//原字符串方阵 
bool vis[N][N];//是否在yizhong里
void dfs(int a,int b,int dep,int fx,node path[]){
	if(dep==7){//递归出口 
		for(int i=0;i<7;i++){
			vis[path[i].x][path[i].y]=true;
		}
		return; 
	}
	//下一个点 
	int bx=a+dx[fx];
	int by=b+dy[fx];
	if(dep==6||g[bx][by]==s[dep+1]) {
//		vis[x][y]=true;要走完整个yizhong才可以确定整个路径上的字母是true的
//放入路径 
path[dep].x=a;
path[dep].y=b;
		dfs(bx,by,dep+1,fx,path);
	}
}
int main() {
cin>>n;
for(int i=0;i<n;i++){
	for(int j=0;j<n;j++){
		cin>>g[i][j];
	}
}
//做dfs 
for(int i=0;i<n;i++){
	for(int j=0;j<n;j++){
		if(g[i][j]=='y'){
			//起点必须是y
			//考虑选择哪一方向延伸,因为同一单词的摆放不能变方向
			for(int k=0;k<8;k++) {
				int x=i+dx[k];
				int y=j+dy[k];
				if(g[x][y]=='i'){//如果第二位是i,说明这个方向可能可以
				dfs(i,j,0,k,path) ;//起点是(i,j)方向是沿着k然后进行dfs 
					
				}
			}
		}
	}
}
//输出答案
for(int i=0;i<n;i++){
	for(int j=0;j<n;j++){
	if(vis[i][j]){//如果在yizhong里面的话 
		cout<<g[i][j];
	}
	 else{
	 	cout<<'*';
	 }
	}
	cout<<endl;
}
return 0;
}
 

P1162 填涂颜色

80分代码

错误原因:每个点仅考虑一个方向一直走(如p1101思想)

#include<bits/stdc++.h>
using namespace std;
const int N=40;
int g[N][N];//存图
bool vis[N][N];//是否在闭合圈内
//方向向量
int dx[4] ={-1,0,1,0};//行 上右下左 
int dy[4] ={0,1,0,-1};//列 上右下左
int n; 
bool dfs(int x,int y,int fx){
int bx=x+dx[fx];
int by=y+dy[fx];
if(bx<0||bx>=n||by<0||by>=n){//不在闭合圈 
return false; 
}
if(g[bx][by]==1){
return true;
}
return dfs(bx,by,fx);//可以继续走  递归也写上return要不然死循环会
}
 
int main(){
cin>>n;
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
cin>>g[i][j];
}
}
 
for(int i=0;i<n;i++) {
for(int j=0;j<n;j++){
if(g[i][j]==1){
continue;
}
int t=0; 
//四个方向
for(int k=0;k<4;k++) {
 
if(dfs(i,j,k)){t++;
}
else{
break;
}
}
if(t==4){//4个true说明在闭合圈 
vis[i][j]=true; 
}
}
}
 
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
if(vis[i][j]){//在闭合圈为false 
cout<<"2 "; 
}
else{
cout<<g[i][j]<<" ";
}
}
cout<<endl;
}
return 0;
}
出错点
用bfs解决了

p1596 lake counting 

解析:

关键是理解题意

题目是说计算水坑数量

一个W会和他八个方向上如果有水都会合并,然后不断往外扩散合并

合并后算一个水坑

所以本题就是对每个W进行dfs将他周围W合并算出一个水坑,看一共多少个水坑

答案

//分析:就是一个w的八个方向上的水都算成一个水坑
//所以用dfs
#include<bits/stdc++.h>
using namespace std;
const int N=110;
char g[N][N];
int n,m;
int ans;
int dx[8]={-1,-1,0,1,1,1,0,-1};//行
int dy[8]={0,1,1,1,0,-1,-1,-1};//列 
void dfs(int a,int b){
    g[a][b]='.';//遍历过这个水
    for(int i=0;i<8;i++) {
        int bx=a+dx[i];
        int by=b+dy[i];
        if(bx>=0&&bx<n&&by>=0&&by<m&&g[bx][by]=='W'){//合并,继续dfs 
            dfs(bx,by);
        }
    }
    return ;//递归出口 ,当不满足上面条件就会退出dfs,dfs要有return(即递归出口)防止会死循环了!
}
int main() {
    cin>>n>>m;
    for(int i=0;i<n;i++){
        for(int j=0;j<m;j++){
            cin>>g[i][j];
        }
    }
    for(int i=0;i<n;i++){
        for(int j=0;j<m;j++){
            if(g[i][j]=='W'){
                dfs(i,j);//对这个水dfs,将他周围的水合并 
                ans++; 
            }
        }
    }
    cout<<ans;
    return 0;
}

完整代码

//分析:就是一个w的八个方向上的水都算成一个水坑
//所以用dfs
#include<bits/stdc++.h>
using namespace std;
const int N=110;
char g[N][N];
int n,m;
int ans;
int dx[8]={-1,-1,0,1,1,1,0,-1};//行
int dy[8]={0,1,1,1,0,-1,-1,-1};//列 
void dfs(int a,int b){
	g[a][b]='.';//遍历过这个水
	for(int i=0;i<8;i++) {
		int bx=a+dx[i];
		int by=b+dy[i];
		if(bx>=0&&bx<n&&by>=0&&by<m&&g[bx][by]=='W'){//合并,继续dfs 
			dfs(bx,by);
		}
	}
	return ;//递归出口 
}
int main() {
	cin>>n>>m;
	for(int i=0;i<n;i++){
		for(int j=0;j<m;j++){
			cin>>g[i][j];
		}
	}
	for(int i=0;i<n;i++){
		for(int j=0;j<m;j++){
			if(g[i][j]=='W'){
				dfs(i,j);//对这个水dfs,将他周围的水合并 
				ans++; 
			}
		}
	}
	cout<<ans;
	return 0;
}

 

posted @ 2025-02-23 20:33  Annaprincess  阅读(15)  评论(0)    收藏  举报