柳叶初零吧 关注:8贴子:598

深度优先搜索

只看楼主收藏回复

深度优先搜索是一种枚举策略,
即从一个状态开始,不断将其扩展至下一个状态,直至无法扩展;
而后回到最近的,还有未扩展状态的节点,继续往其他方向扩展。
以此枚举所有可能的解。
采用递归回溯方法进行深度优先搜索也称“回溯法”


IP属地:广东1楼2011-03-03 19:10回复
    深度优先搜索在穷举时极为常用。
    一些例题:
    1.全排列
    输入正整数n,按字典顺序输出1~n所有可能的排列
    如输入3,输出123,132,213,231,312,321。
    2.八皇后问题
    在8x8的国际象棋棋盘上放置8个皇后,使其不能互相攻击到(即任意两个皇后不能同行同列同对角线),问有多少种放法。
    3.加法拆分
    输入正整数n,将其分解成所有可能的相加的形式并输出
    如n=4,则输出
    4=1+1+1+1
    4=1+1+2
    4=1+3
    4=2+2
    4.0-1背包
    有n个物品,其中第i个物品具有Vi的价值和Wi的重量。现有一背包,能装下总重量为M的物品。问能装入背包的物品最大价值是多少?


    IP属地:广东2楼2011-03-03 19:17
    回复
      回溯法一般模板:
      void f(当前步) {
          for (枚举状态){
              if 可用 {
                  if 完成一个方案
                      输出,记录;
                  做标记;
                f(下一步);
                 取消标记;
             }
          }
      }


      IP属地:广东3楼2011-03-13 19:33
      回复
        或者
        void f(当前步) {
             if 完成一个方案 {
                 输出,记录;
                return;
            }
             for (枚举状态){
                 if 可用 {
                    做标记;
                    f(下一步);
                     取消标记;
                }
             }
        }
        


        IP属地:广东4楼2011-03-13 19:34
        回复
          回复:3楼
          “记录”后面加return


          IP属地:广东5楼2011-03-13 19:35
          回复
            回复:6楼
            额……错了= =
            是continue


            IP属地:广东7楼2011-03-13 19:52
            回复
              全排列标程(应该结构比较清晰了,比较好消化理解):
              #include <stdio.h>
              int a[100],n,used[100]={0};
              void prt() {     //     输出
                   int k;
                   for (k=1;k<=n;k++)
                       printf("%d",a[k]);
                   printf("\n");
              }
              void find(int i) {
                   int j;
                   if (i>n) {     //     i>n意味着排列已经完成
                       prt();
                       return;
                   }
                   for (j=1;j<=n;j++)
                       if (used[j]==0) {
                           used[j]++;     //     记录该数已经用过
                           a[i]=j;
                           find(i+1);
                           used[j]--;     //     枚举下一个之前要取消之前的记录
                           a[i]=0;
                       }
              }
              int main() {
                   scanf("%d",&n);
                   find(1);
                   getchar();
                   getchar();
              }


              IP属地:广东8楼2011-03-13 22:49
              回复
                那个used[j]++; 和used[j]--;还是分别改成赋值1或0吧,就是1表示已经使用过,0表示未使用


                IP属地:广东9楼2011-03-13 22:58
                回复
                  唉……希望你妈能理解吧……
                  信息学奥林匹克竞赛也是中学五门奥赛之一啊……
                  多少人指望着拿个省一求保送呢……


                  IP属地:广东10楼2011-03-13 22:59
                  回复
                    说实话柳你学得挺快的……
                    而且你们省比起我们湖南来说,拿信息学竞赛分区联赛省一等奖的门槛要低出不少……
                    你还需要看的:半本《数据结构》+ 两本《奥赛经典》(基础篇、提高篇)拿省一基本没问题了
                    另外大学理工科几乎必修C/C++,计算机等级考试也必须会C/C++。现在学也是为以后打下基础。


                    IP属地:广东11楼2011-03-13 23:10
                    回复
                      回复:13楼
                      所有对角线


                      IP属地:广东14楼2011-03-15 22:50
                      回复
                        回复:3楼
                        回复:4楼
                        这两个模板选一个记住了做搜索就方便些,另外Debug技巧真的很重要。


                        IP属地:广东17楼2011-03-27 00:29
                        回复
                          回复:7楼
                          别忘了这个改动


                          IP属地:广东18楼2011-03-27 00:29
                          回复