一、定义
基本思想
子集树与排列树
//形参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]); //恢复状态
}
}
二、装载问题
代码实现:
#define NUM 100
int n; //集装箱的数量
int c; //轮船的载重量
int w[NUM]; //集装箱的重量数组
int x[NUM]; //当前搜索的解向量
int r; //剩余集装箱的重量
int cw; //当前轮船的载重量
int bestw; //当前最优载重量
int bestx[NUM]; //当前最优解
//形参表示搜索第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]; //恢复状态
}
r = 0;
for(int i=1;i<=n;i++)
{
scanf("%d", &w[i]);
r += w[i];
}
三、0-1背包问题
代码实现:
#define NUM 100
int c; //背包的容量
int n; //物品的数量
int cw; //当前重量
int cv; //当前价值
int bestv; //当前最优价值
//描述每个物品的数据结构
struct Object{
int w; //物品的重量
int v; //物品的价值
double d; //物品的单位重量价值比
}Q[NUM]; //物品的数组
//对物品以单位重量价值比递减排序的因子是:
bool cmp(Object a, Object b)
{
if(a.d>=b.d) return true;
else return false;
}
//物品的单位重量价值比是在输入数据时计算的:
for(int i=0; i<n; i++)
{
scanf("%d%d",&Q[i].w,&Q[i].v);
Q[i].d = 1.0*Q[i].v/Q[i].w;
}
//使用C++标准模板库的排序函数sort()排序:
sort(Q, Q+n, cmp);
//形参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是回溯的深度
int Bound(int i)
{
int cleft = c-cw; //背包剩余的容量
int b = cv; //上界
//尽量装满背包
while (i<n && Q[i].w<=cleft)
{
cleft -= Q[i].w;
b += Q[i].v;
i++;
}
//剩余的部分空间也装满
if (i<n) b += 1.0*cleft*Q[i].v/Q[i].w;
return b;
}
四、N皇后
代码实现:
#include<bits/stdc++.h>
using namespace std;
#define NUM 20
int n;
int x[NUM];
int sum;
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;
}
void Backtrack(int t)
{
int i;
if (t>n)
{
sum++;
for (i=1;i<=n;i++)
{
cout<<x[i]<<" ";
cout<<endl;
}
}
else{
for (i=1; i<=n; i++)
{
x[t] = i;
if (Place(t)!=0) Backtrack(t+1);
}
}
}
int main()
{
while (cin>>n)
{
sum = 0;
Backtrack(1);
cout<<"Total="<<sum<<endl;
}
return 0;
}