算法设计与分析——第6章 回溯算法

算法设计与分析——第6章 回溯算法

回溯法的基本思想

算法设计与分析——第6章 回溯算法

算法设计与分析——第6章 回溯算法

算法设计与分析——第6章 回溯算法

子集树与排列树

算法设计与分析——第6章 回溯算法

回溯算法搜索子集树的伪代码

//形参t为树的深度,根为1

void backtrack (int t)

{

  if (t>n) update(x);

  else

    for (int i=0; i<=1; i++)  //每个结点只有两个子树

    {

      x[t]=i;         //0/1

      if (constraint(t) && bound(t)) backtrack(t+1);

    }

}

¢约束函数constraint(t)和限界函数bound(t),称为剪枝函数
¢函数update(x)是更新解向量x的。
¢约束函数constraint(t),一般可以从问题描述中找到

算法设计与分析——第6章 回溯算法

//形参t为树的深度,根为1

void backtrack (int t)

{

  if (t>n) update(x);

  else

    for (int i=t; i<=n; i++)

    {

      //为了保证排列中每个元素不同,通过交换 来实现

      swap(x[t], x[i]);

      if (constraint(t) && bound(t)) backtrack(t+1);

      swap(x[t], x[i]);    //恢复状态

    }

}

装载问题

算法设计与分析——第6章 回溯算法

01背包问题

算法设计与分析——第6章 回溯算法

算法设计与分析——第6章 回溯算法

图的m着色问题

算法设计与分析——第6章 回溯算法

//形参t是回溯的深度,从1开始

void BackTrack(int t )

{

  int i;

  //到达叶子结点,获得一个着色方案

  if( t > n )

  {

    sum ++ ;

    for(i=1; i<=n ;i++)

      printf("%d ",x[i]);

    printf("\n");

  }

  else

    //搜索当前扩展结点的m个孩子

    for(i=1; i<=m; i++ )

    {

      x[t] = i;

      if( Same(t) ) BackTrack(t+1);

      x[t] = 0;

    }

}

n皇后问题

算法设计与分析——第6章 回溯算法

//形参t是回溯的深度,从1开始

void Backtrack(int t)

{

  int i;

  //到达叶子结点,获得一个可行方案。累计总数,并输出该方案

  if (t>n)

  {

    sum++;  //是全局变量

    for (i=1; i<=n; i++)

      printf(" %d", x[i]);

    printf("\n");

  }

  else

    for (i=1; i<=n; i++)

    {

      x[t] = i;

      if (Place(t)) Backtrack(t+1);

    }

}

旅行商问题TSP问题)

算法设计与分析——第6章 回溯算法

//形参t是回溯的深度,从2开始

void Backtrack(int t)

{

  //到达叶子结点的父结点

  if(t==n)

  {

    if(a[x[n-1]][x[n]]!= NoEdge && a[x[n]][1]!= NoEdge &&

      (cc + a[x[n-1]][x[n]]+a[x[n]][1]<bestc||bestc== NoEdge))

    {

      for(int i=1; i<=n; i++)

        bestx[i] = x[i];

      bestc = cc + a[x[n-1]][x[n]] + a[x[n]][1];

    }

    return;

  }

else

  {

    for(int i=t; i<=n; i++)

    {

      if(a[x[t-1]][x[i]]!= NoEdge &&

        (cc + a[x[t-1]][x[i]]< bestc||bestc == NoEdge))

      {

        swap(x[t],x[i]);

        cc += a[x[t-1]][x[t]];

        Backtrack(t+1);

        cc -= a[x[t-1]][x[t]];

        swap(x[t],x[i]);

      }

    }

  }

}

流水作业调度问题

算法设计与分析——第6章 回溯算法

流水作业调度问题回溯算法的实现

//形参t是回溯的深度,从1开始

void Backtrack(int t)

{

  //到达叶子结点,更新最优解

  if (t>n)

  {  

    bestf = f;

    for (int i=1; i<=n; i++)

      bestx[i]=x[i];

    return;

  }

for (int i=t; i<=n; i++)

  {

    f1 += job[x[i]][1];

    f2[t] = ((f2[t-1]>f1) ? f2[t-1] : f1)+job[x[i]][2];

    f += f2[t];

    if (f<bestf)       //剪枝

    {

      swap(x[t], x[i]);

      Backtrack(t+1);

      swap(x[t], x[i]);

    }

    f1 -= job[x[i]][1];

    f -= f2[t];

  }

}