回溯算法,模板,拔河,旅行商,连续邮资问题题解
文章目录
- 回溯算法模板
- 递归回溯
- 迭代回溯
- 子集树
- 排列树
- 题目
- 拔河问题
- 旅行商问题
- 连续邮资问题
回溯算法模板
递归回溯
回溯法对解空间做深度有限搜索,因此在一般情况下可用递归函数来实现回溯法如下:
模板:
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);}elset++;}}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<iostream>using namespace std;#define N 100int 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 75void backtrace(int k){int i;if(k>n/2){if(tempw==totalw/2){// cout<<"tempw="<<tempw<<endl;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<<x[j]<<" ";
// }
// cout<<endl;
// cout<<"tempw=="<<tempw<<endl;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<iostream>
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 <stdio.h>
#include<malloc.h>#define MAX_NM 10
#define MAX_POSTAGE 1024
#define INF 2147483647int 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;sscanf("%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;
}
回溯算法,模板,拔河,旅行商,连续邮资问题题解相关推荐
- 力扣刷题-python-回溯算法-1(回溯算法模板、题型)
文章目录 1.回溯算法 2.回溯算法模板 3.回溯实例(77.216.17.39.40.131.93.78.90.491.46.47) 4.总结 1.回溯算法 回溯算法的本质就是穷举,最多再加上剪枝, ...
- 鲸鱼优化算法WOA求解旅行商TSP优化问题(2022.6.2)
鲸鱼优化算法WOA求解旅行商TSP优化问题(2022.6.2) 引言 1.鲸鱼优化算法WOA 1.1 WOA算法原理介绍 1.1.1 包围猎物 1.1.2 气泡网式攻击猎物(开发阶段) 1.1.3 寻 ...
- 回溯算法模板之:332. 重新安排行程
题目链接:332.重新安排行程 分析:需要重新排列行程,并且需要按照自然排序的大小,所以第一步就先进行字典的创建,key是起始地,value是可到达所有的目的地,然后对value进行排序.使用回溯算法 ...
- 算法:连续邮资问题(回溯+动态规划+剪枝)
问题描述 假设国家发行了n种不同面值的邮票,并且规定每张信封上最多只允许m张邮票.连续邮资问题要求对于给定的n和m的值,给出邮票面值的最佳设计,即在1张信封上可贴出从邮资1开始,增量为1的最大连续邮资 ...
- Nuist集训队作业:深度优先搜索(回溯算法)
Nuist集训队第一次作业:深度优先搜索(回溯算法) 引例 深搜基本思想及回溯算法模板 P1706 全排列问题 P1219 八皇后 P1605 迷宫 P1101 单词方阵 小结 引例 国际西洋棋棋手马 ...
- 数字拆分问题算法回溯_回溯算法:求子集问题!
给「代码随想录」一个星标吧! ❝ 认识本质之后,这就是一道模板题 通知:我将公众号文章和学习相关的资料整理到了Github :https://github.com/youngyangyang04/le ...
- 回溯算法团灭子集、排列、组合问题
回溯算法团灭子集.排列.组合问题 一.子集 给定一组不含重复元素的整数数组 nums,返回该数组所有可能的子集(幂集). 说明:解集不能包含重复的子集. 示例: 输入: nums = [1,2,3] ...
- 回溯算法——复原IP地址(Leetcode 93)
题目选自Leetcode 93.复原IP地址 由于我们需要找出所有可能复原出的 IP 地址,因此可以考虑使用回溯的方法,对所有可能的字符串分隔方式进行搜索,并筛选出满足要求的作为答案. 通俗来讲,就是 ...
- 算法训练Day24 | 回溯算法理论基础;LeetCode77.组合(经典的回溯问题)
目录 回溯算法理论基础 1. 什么是回溯法 2. 回溯法的效率 3. 回溯法解决的问题 4. 如何理解回溯法 5. 回溯法模板-- 回溯三部曲 6. 总结 LeetCode77.组合 1. 思路 2. ...
最新文章
- 读javascript高级程序设计03-函数表达式、闭包、私有变量
- 实践教程|YOLOX目标检测ncnn实现
- pgsql 相关的命令
- 换个姿势学数学:二次函数与拆弹部队
- BZOJ5323 洛谷4562:[JXOI2018]游戏——题解
- 数据为什么要可视化?如何可视化?
- 在阿里做博士后是一种怎样的体验?
- php 连接数据库 pod,PHP PDO类解决数据库连接问题
- git submodule使用
- 利用模板模式重构JDBC操作
- python自动化运维书籍推荐_《Python 自动化运维:技术与最佳实践》
- Java中java.lang.Class的初步学习
- sql server 别名_SQL Server别名概述
- 人工智能时代!Python跃升编程语言第一名!
- KEIL识别不出野火STM32仿真器问题解决
- 【MySQL】根据数据表中日期字段查询某个月每一天的数据量?查询数据表中所有日期每天的数据量?近三天每天数据量?
- A40I构建编译应用程序的SDK环境
- MySQL--管理数据库表相关操作
- 【笔记】微信小程序基础
- Android eSIM-LPA基于Android13的实现
热门文章
- Linux如何创建文件在指定的目录?
- MySQL 数据库备份一键执行脚本 --- 全库备份和增量备份
- Nginx显示500错误原因和解决方法
- linux 我的世界 跨平台联机,《我的世界》将支持跨平台联机
- javaweb总结——孤傲苍狼
- java中admin什么意思_Spring Boot Admin 的使用详解
- 怎么确定电磁波的相位
- 王者荣耀新24赛季服务器维护,《王者荣耀》s24赛季改动内容分享 s24新赛季更新公告...
- Python金融大数据分析——第9章 数学工具 笔记
- 记录vue中使用scss报红但是不影响css样式,代码行会提示css-rcurlyexpected这个问题