回溯算法

 

1、装载问题
//形参表示搜索第t层结点
void Backtrack(int t)
{
  //到达叶子结点
  if(t>n)
  { 
    //更新最优解
    if(cw>bestw)
    {
      for(int i=1; i<=n; i++) 
        bestx[i] = x[i];
      bestw = cw;
    }
    return;
}
//更新剩余集装箱的重量
  r -= w[t];
  //搜索左子树
  if(cw+w[t]<=c)
  {
    x[t] = 1;
    cw += w[t];
    Backtrack(t+1);
    cw -= w[t];
  }
  //搜索右子树
  if(cw+r>bestw)
  {
    x[t]=0;
    Backtrack(t+1);
  }
r += w[t];  //恢复状态
}

2、0-1背包问题
//形参i是回溯的深度,从0开始
void backtrack(int i)
{
  //到达叶子结点时,更新最优值
  if (i+1>n) {bestv = cv; return;}
  //进入左子树搜索
  if (cw+Q[i].w<=c)
  {
    cw += Q[i].w;
    cv += Q[i].v;
    backtrack(i+1);
    cw -= Q[i].w;
    cv -= Q[i].v;
  }
  //进入右子树搜索
  if (Bound(i+1)>bestv) backtrack(i+1);
}

//形参i是回溯的深度,从0开始
void backtrack(int i)
{
  //到达叶子结点时,更新最优值
  if (i+1>n) {bestv = cv; return;}
  //进入左子树搜索
  if (cw+Q[i].w<=c)
  {
    cw += Q[i].w;
    cv += Q[i].v;
    backtrack(i+1);
    cw -= Q[i].w;
    cv -= Q[i].v;
  }
  //进入右子树搜索
  if (Bound(i+1)>bestv) backtrack(i+1);
}


3、图的M着色问题
//形参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;
    }
}

//检查相邻结点的着色是否一样
//形参t是回溯的深度
bool Same(int t)
{
  int i;
  for(i=1; i<=n; i++ )
    if( (a[t][i] == 1) && (x[i] == x[t]))
      return false;
  return true;
}


4、N皇后问题
//形参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);
    }
}
//检查当前皇后位置的约束函数
inline bool Place(int t) 
{ 
  int i; 
  for (i=1; i<t; i++) 
    if ((abs(t-i) == abs(x[i]-x[t])) || (x[i] == x[t])) 
      return false; 
  return true; 
}


5、旅行商问题
//形参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]);
      }
    }
  }
}


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值