吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 1020|回复: 15
收起左侧

[求助] dfs递归回溯的一个好奇怪的问题,大家来看看

  [复制链接]
1847292359 发表于 2022-1-21 14:15
本帖最后由 1847292359 于 2022-1-21 14:50 编辑

楼主在学习深度搜索回溯,碰到了一个好奇怪的问题,我附上图和代码一起描述问题,大家结合两者看一下
微信截图_20220121140441.png
我跟着代码边跑边分析,并且用cout输出以便理清代码执行状况,问题在输出那句“7  J5”,  他表示将进入dfs(7),并且是当前在x=5的时候进入的,但是所写代码里面判断当x=5的时候我并没有让他进入dfs(7),那么他这句输出为什么会这样?结合代码跑一遍,不是应该继续退到上一个x吗?


是代码写得有问题还是我理解dfs有问题呢?(代码是C++写的简单dfs)


[C++] 纯文本查看 复制代码
#include<bits/stdc++.h>
using namespace std;

bool yg[7];
//yg = 用过  用来判断的

void dfs(int x)
{
yg[x] = 1;//每来一次就先占了他  后面再释放

switch(x) {
        case 1:
                   if(!yg[2]){
                           cout<<"2  J"<<x<<endl;//J=叫他进的数                  
                           dfs(2) ;                             
                   }
                   if(!yg[4]){
                           cout<<"4  J"<<x<<endl;                                     
                           dfs(4) ;                             
                   }
             
        case 2:
                    if(!yg[3]){
                        cout<<"3  J"<<x<<endl;                                       
                           dfs(3) ;                             
                   }
                    if(!yg[7]){
                        cout<<"7  J"<<x<<endl;                                       
                           dfs(7) ;                             
                   }

        case 3:
                   if(!yg[4]){
                           cout<<"4  J"<<x<<endl;                                     
                           dfs(4) ;                             
                   }
                  if(!yg[5]){
                          cout<<"5  J"<<x<<endl;                                   
                           dfs(5) ;                             
                   }
                   if(!yg[7]){
                           cout<<"7  J"<<x<<endl;                                     
                           dfs(7) ;                             
                   }                        
        case 4:  if(!yg[5]){
                   cout<<"5  J"<<x<<endl;        
                           dfs(5) ;                             
                   }
                           if(!yg[3]){
                        cout<<"3  J"<<x<<endl;                                                              
                           dfs(3) ;                             
                   }        
        case 5: //问题这里
              if(!yg[6]){
                     cout<<"6  J"<<x<<endl;                   
                           dfs(6) ;                             
                   } 
                    if(!yg[4]){
                        cout<<"4  J"<<x<<endl;                                       
                           dfs(4) ;                             
                   } 
                    if(!yg[3]){
                        cout<<"3  J"<<x<<endl;                                       
                           dfs(3) ;                             
                   } 
        case 6:
                     if(!yg[5]){
                         cout<<"5  J"<<x<<endl;                                             
                           dfs(5) ;                             
                   } 
                                                      
                       if(!yg[7]){
                          cout<<"7  J"<<x<<endl;                                                  
                           dfs(7) ;                             
                   }    
        case 7:
                    if(!yg[6]){
                        cout<<"6  J"<<x<<endl;                                       
                           dfs(6) ;                             
                   }
                   if(!yg[3]){
                           cout<<"3  J"<<x<<endl;                                     
                           dfs(3) ;                             
                   } 
                   if(!yg[2]){
                           cout<<"2  J"<<x<<endl;                             
                           dfs(2) ;                             
                   }                                                                                              
}
yg[x] = 0;//这次用完了 释放
cout<<x<<"t"<<endl;//t表示退出  即x退出了
}
int main(){
   dfs(1) ; 
   }



就是每次dfs完了之后他应该退回到上一个让他进入dfs的地方继续执行下去,但是这里为什么会出现这种情况?
按照本例代码运行的理论走势,他应该是一直退到x=3的情况,然后进入dfs(5)


但他实际走向并不是这样,不知道为什么

希望大家可以解答下,一直搞不明白

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

 楼主| 1847292359 发表于 2022-1-21 14:37
本帖最后由 1847292359 于 2022-1-21 14:48 编辑

smldhz 发表于 2022-1-21 14:31
switch case break

我并不想让他这么快就break
我是想让他在当前情况继续判断下去

也就是说当他回溯之后,继续根据x的情况判断下去 (比如x=5,他还会根据条件情况进入dfs(6)/dfs(4)/dfs(3),如果都不符合条件才跳到末尾结束当前一轮的switch)



按照本例代码运行的理论走势,他应该是退到x=3的情况,然后进入dfs(5)


但他实际走向并不是这样,不知道为什么
夕阳枫 发表于 2022-1-21 14:28
smldhz 发表于 2022-1-21 14:31
SpeII 发表于 2022-1-21 14:35
3楼正解,switch遇到break结束,或者程序默认执行到末尾结束.
 楼主| 1847292359 发表于 2022-1-21 14:40
本帖最后由 1847292359 于 2022-1-21 14:47 编辑
SpeII 发表于 2022-1-21 14:35
3楼正解,switch遇到break结束,或者程序默认执行到末尾结束.


我并不想让他这么快就break
我是想让他在当前情况继续判断下去

也就是说当他回溯之后,继续根据x的情况判断下去 (比如x=5,他还会根据条件情况进入dfs(6)/dfs(4)/dfs(3),如果都不符合条件才跳到末尾结束当前一轮的switch)



按照本例代码运行的理论走势,他应该是退到x=3的情况,然后进入dfs(5)


但他实际走向并不是这样,不知道为什么
SpeII 发表于 2022-1-21 15:09
1847292359 发表于 2022-1-21 14:40
我并不想让他这么快就break
我是想让他在当前情况继续判断下去

switch的case穿透,后面case都会执行
smldhz 发表于 2022-1-21 15:58
1847292359 发表于 2022-1-21 14:40
我并不想让他这么快就break
我是想让他在当前情况继续判断下去

不是你想的那样 case 5: 执行完了之后就return了 case 5: 之后没有break的话 case 6 7 都会被执行
是的 你没看错 case 5:之后的所有case 都会进去并执行
你可以跑个例子看看
[C++] 纯文本查看 复制代码
#include <iostream>
using namespace std;

int main(){
    int x = 3;
    switch(x){
        case 1:
            cout << "1" << endl; 
        case 2:
            cout << "2" << endl; 
        case 3:
            cout << "3" << endl; 
        case 4:
            cout << "4" << endl; 
        case 5:
            cout << "5" << endl;   
    }
    return 0;
}
z1390595 发表于 2022-1-21 16:39
楼上的回复是对的。
楼主的问题要解决的话,可以在case 6:前一行加个break;,就是在楼主想做的三个判断完成之后加,这样就可以都判断完,然后不会执行case 6及之后的case了。不加break;会导致后面的所有case都被执行一遍。
 楼主| 1847292359 发表于 2022-1-21 17:02
z1390595 发表于 2022-1-21 16:39
楼上的回复是对的。
楼主的问题要解决的话,可以在case 6:前一行加个break;,就是在楼主想做的三个判断完 ...

确实是那个switch的问题,我把他改为了if 微信截图_20220121165243.png

我写这段代码目的是为了解决上图这个问题

代码如下(字母我用如图的数字代替,一串数字组合表示一个字符表达)
[C++] 纯文本查看 复制代码
#include<bits/stdc++.h>
using namespace std;
int ans = 0;
string z;
string sz[5040];
bool yg[7];

void dfs(int x)
{
        ans ++;        
z = z + to_string(x);
sz[ans] = z;
yg[x] = 1;//每来一次就先占了他  后面再释放

if(x == 1){
if(!yg[2]){
                
                           dfs(2) ;
                                             
                   }
                   if(!yg[4]){
                                             
                           dfs(4) ;
                                                      
                   }        
}
else if(x ==2 ){
        
          if(!yg[3]){
                                       
                           dfs(3) ;
                                                        
                   }
                    if(!yg[7]){
                                       
                           dfs(7) ;
                                                        
                   }
}
else if(x ==3 ){
          if(!yg[4]){
                             
                           dfs(4) ;
                                                        
                   }
                  if(!yg[5]){
                                           
                           dfs(5) ;
                                                       
                   }
                   if(!yg[7]){
                             
                           dfs(7) ;
                                                        
                   }                    
}
else if(x ==4 ){
         if(!yg[5]){
                
                           dfs(5) ;
                                                      
                   }
                           if(!yg[3]){
                                                                      
                           dfs(3) ;
                                                     
                   } 
}
else if(x ==5 ){
        if(!yg[6]){
                           
                           dfs(6) ;
                                                     
                   } 
                    if(!yg[4]){
                               
                           dfs(4) ;
                                                      
                   } 
                    if(!yg[3]){
                                       
                           dfs(3) ;
                                                     
                   } 
}
else if(x ==6 ){
         if(!yg[5]){
                                             
                           dfs(5) ;
                                                      
                   } 
                                                      
                       if(!yg[7]){
                                                          
                           dfs(7) ;
                                                     
                   }    
}
else if(x ==7 ){
        if(!yg[6]){
                                               
                           dfs(6) ;
                                             
                   }
                   if(!yg[3]){
                                              
                           dfs(3) ;
                                             
                   } 
                   if(!yg[2]){
                                       
                           dfs(2) ;
                                             
                   }        
}
z.pop_back();      //删除最后一个数字
yg[x] = 0;//这次用完了 释放
//cout<<x<<"t"<<endl;//t表示退出  即x退出了
}
int main(){
   dfs(1) ;  //表示从第一个开始跑
   z = ""  ; 
    dfs(2) ;                    //第一个跑完了,接着不要第一个跑第二个数字
   z = ""  ; 
   dfs(3) ; 
   z = ""  ;
    dfs(4) ; 
   z = ""  ; 
    dfs(5) ; 
   z = ""  ;
      dfs(6) ; 
   z = ""  ;
       dfs(7) ; 

set <string> set;     //整一个set来去重  
   for(int e = 0;e<=ans;e++){
                 int len = sz[e].size();
                           sort(&sz[e][0],&sz[e][len]); //统一排序  比如“1234”和“4213”是同一个 ,排序后set会自动去重
                       
   }
   for(int e = 0;e<=ans;e++){
           
            
           set.insert(sz[e]) ;     //排序好之后添加到set里面,如果重复了set会自动忽略
           
   }
   cout<<set.size();  //最后获取数量
   }


正确求解答案是80,我这段代码输出是74。。不知道哪里出错了。。
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-11-25 16:47

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表