回溯法对解空间做深度有限搜索,因此在一般情况下可用递归函数来实现回溯法如下:
模板:
void backtrace(int t){
if(t>n)
output(x);
else{
for(int i=f(n,t);i<=g(n,t);i++){
x[t]=i;
if(constraint(t)&&bound(t)){
backtrace(t+1);
}
}
}
}
采用树的非递归深度优先遍历算法,也可将回溯法便是为一个非递归的迭代过程如下:
模板:
void backtrace(int t){
if(t>n){
output();
}
while(t<n){
if(f(n,t)<=g(n,t)){
for(int i=f(n,t);i<=g(n,t);i++){
x[t]=h(i);
if(constraint(t)&&bound(t)){
output(x);
}
else
t++;
}
}
else{
t--;
}
}
}
模板:
void backtrace(int t){
if(t>n){
output();
}
else{
for(int i=0;i<=1;i++){
x[t]=i;
if(constraint(t)&&bound(t)){
backtrace(t+1);
}
}
}
}
模板:
void backtrace(int t){
if(t>n){
output();
}
else{
for(int i=t;i<=n;i++){
swap(x[i],x[t]);
if(constraint(t)&&bound(t)){
backtrace(t+1);
}
swap(x[i],x[t]);
}
}
}
#include
using namespace std;
#define N 100
int w[N],n,totalw,tempw,temp_person_num,x[N];
void swap(int *a,int *b){
int temp=*a;
*a=*b;
*b=temp;
}
//12
//48 43 57 64 50 52 18 34 39 56 16 75
void backtrace(int k){
int i;
if(k>n/2){
if(tempw==totalw/2){
// cout<<"tempw="<
for(i=1;i<=n/2;i++){
cout<<x[i]<<" ";
}
cout<<endl;
}
}
else
{
for(i=k;i<=n;i++){
swap(&x[k],&x[i]);
tempw+=x[k];
// for(int j=1;j<=n;j++){
// cout<
// }
// cout<
// cout<<"tempw=="<
if(tempw<=totalw/2){
backtrace(k+1);
}
tempw=tempw-x[k];
swap(&x[k],&x[i]);
}
}
}
int main(){
int i;
//拔河总人数
cin>>n;
//初始化装入对象
for(i=1;i<=n;i++){
cin>>x[i];
totalw+=x[i];
}
backtrace(1);
return 0;
}
#include
using namespace std;
#define MAX 1000
int g[100][100], x[100], bestx[100];
int cl = 0, bestl = MAX, n;
void Traveling(int t) {
int j;
if (t > n) { //到达叶子结点
if (g[x[n]][1] != -1 && (cl + g[x[n]][1] < bestl)) { //推销员到的最后一个城市与出发的城市之间有路径,且当前总距离比当前最优值小
for (j = 1; j <= n; j++)
bestx[j] = x[j];
bestl = cl + g[x[n]][1];
}
} else { //没有到达叶子结点
for (j = t; j <= n; j++) { //搜索扩展结点的左右分支,即所有与当前所在城市临近的城市
if (g[x[t - 1]][x[j]] != -1 && (cl + g[x[t - 1]][x[j]] < bestl)) { //若果第t-1个城市与第t个城市之间有路径且可以得到更短的路线
swap(x[t], x[j]); //保存要去的第t个城市到x[t]中
cl += g[x[t - 1]][x[t]]; //路线长度增加
Traveling(t + 1); //搜索下一个城市
cl -= g[x[t - 1]][x[t]];
swap(x[t], x[j]);
}
}
}
}
int main() {
int i, j;
cin >> n;
for (i = 1; i <= n; i++)
for (j = 1; j <= n; j++)
cin >> g[i][j];
for (i = 1; i <= n; i++) {
x[i] = i;
bestx[i] = 0;
}
Traveling(2);
cout << "城市路线:" << endl;
for (i = 1; i <= n; i++)
cout << bestx[i] << ' ';
cout << bestx[1];
cout << endl;
cout << "最短路线长度:" << endl;
cout << bestl << endl;
return 0;
}
#include
#include
#define MAX_NM 10
#define MAX_POSTAGE 1024
#define INF 2147483647
int n, m;
int x[MAX_NM], ans[MAX_NM], y[MAX_POSTAGE], maxStamp, r;
/*
* backtrack(i)表示x[0...i-1]这i张邮票已经完全确定,
* 相应于x[0...i-1]的最大连续邮资区间r和每种邮资所需要的
* 最少邮票张数y[0...r]也都确定,现在枚举x[i]
* 的每个值,确定x[i]
*/
void backtrack(int i) {
int *backup_y, backup_r;
int next, postage, num, tmp;
if(i >= n) {
if(r > maxStamp) {
maxStamp = r;
for(tmp = 0; tmp < n; tmp++)
ans[tmp] = x[tmp];
}
return;
}
//临时的存储贴出某价值邮票所需的邮票数
backup_y = (int*)malloc(MAX_POSTAGE * sizeof(int));
for(tmp = 0; tmp < MAX_POSTAGE; tmp++)backup_y[tmp] = y[tmp];
//临时的最大邮资区间
backup_r = r;
//下一个票数的区间应该是大于x[i-1]并且小于等于当前的最大邮资区间+1,因为如果定义r+2作为下一个,那么r+1就会空出来
for(next = x[i - 1] + 1; next <= r + 1; next++) {
/* update x[i] */
//第i个位置的邮资
x[i] = next;
/* update y */
for(postage = 0; postage < x[i-1] * m; postage++) {
if(y[postage] >= m)continue;
for(num = 1; num <= m - y[postage]; num++)
if(y[postage] + num< y[postage + num * next] //y[postage]是不能是inf
&& (postage + num * next< MAX_POSTAGE)) //下标不要越界了
y[postage + num * next] = y[postage] + num;
}
/* update r */
while(y[r + 1] < INF) r++;
backtrack(i + 1);
/* restore */
r = backup_r;
for(tmp = 0; tmp < MAX_POSTAGE; tmp++) y[tmp] = backup_y[tmp];
}
free(backup_y);
}
int main() {
int i;s
scanf("%d%d", &n, &m);
x[0] = 1;
//r的定义为最大邮资区间,每一个都是1就是最大的范围了。
r = m;
//当前情况下贴出某邮资需要的最少邮票数,y[i]=i.
for(i = 0; i <= r; i++) y[i] = i;
while(i < MAX_POSTAGE) y[i++] = INF;
//记录最后的最大邮资区间
maxStamp= 0;
backtrack(1);
printf("max stamp is: %d\n", maxStamp);
for(i = 0; i < n; i++)
printf("%4d", ans[i]);
return 0;
}