回溯法(排列、子集和、TSP问题、n皇后问题、01背包问题)

本文介绍了如何利用回溯法解决五个经典问题:1. 从给定字母中找出所有排列;2. 解决子集和问题,判断是否存在和为目标值的子集;3. 解决旅行商问题(TSP),找到最短旅行路径;4. 实现n皇后问题,找到所有合法的皇后放置方案;5. 应用回溯法解决0-1背包问题,找到能装入背包的最大价值。每个问题都有详细的输入输出格式和示例,并给出了关键思路。
摘要由CSDN通过智能技术生成

1.排列

任务描述
1.设计算法从前m个大写字母(m≤26)种取出n个字母的所有排列(组合),并编程实现

输入格式
输入M N
1<=M=26, N<=M

输出格式
按字典序输出排列
注意:行末不输出多余空格

Sample Input
4 2

Sample Output
A B
A C
A D
B A
B C
B D
C A
C B
C D
D A
D B
D C

思路:使用一个标记数组’flag’来表示已经使用过的字母,再次调用回溯函数时已经被标记的字母将不被选中

#include"stdio.h"
char a[26];
int m,n;
int flag[26],ans[26];
void search(int c){
   
  int i;
  if(c==n){
   
    for(i=0;i<n-1;i++) printf("%c ",a[ans[i]]);
    printf("%c\n",a[ans[i]]);
    
  }
  else{
   
    for(int i=0;i<m;i++){
   
      if(flag[i]) continue;
      ans[c]=i;         //存放当前c位置对应的字母(0~m)
      flag[i]=1;        //当前字母做标记,表示已被引用
      search(c+1);
      flag[i]=0;
    }
  }

}

int main(int argc, const char** argv) {
   
    
    scanf("%d%d",&m,&n);
    
    for(int i=0;i<26;i++) a[i]='A'+i;

    search(0); 
    return 0;
}

2.子集合

任务描述

设集合S={x1,x2,…,xn}是一个正整数集合,c是一个正整数,子集和问题判定是否存在S的一个子集S1,使S1中的元素之和为c。试设计一个解子集和问题的回溯法

输入格式

输入数据第1行有2个正整数n和c,n表示S的大小,c是子集和的目标值 接下来的1行中,有n个正整数,表示集合S中的元素 n<10,c<100

输出格式

输出所有满足条件的集合,当问题无解时,输出“No Solution!”。 注意:末尾不输出多余空格 按照输入顺序输出,比如第一个满足条件的子集合是[2 2 6],那么就先输出它,子集合内的数也按照输入顺序输出

Sample Input

5 10 2 2 6 5 4

Sample Output

2 2 6 6 4

思路:同样是使用标记数组,这里用bool vis[N]来标记当前数字i是否被记入,对数字i进行标记和不标记,类似于二叉树,被标记的数字i计入数字和,判断当前数字和是否满足输出条件,不满足则调用下一层数字i+1。对数字i取消标记,使其进入下一层数字i+1,并对i+1进行标记和不标记两种处理方式,直到所有数字遍历完。

#include"stdlib.h"
#include"string.h"
#include "stdio.h"
 
const int N = 1000; 
 
int arr[N]; // 存储几何元素
bool vis[N]; // 存储集合状态
int valSum=0;  //当前和
int num,sum;

void search(int n){
   //n是当前数字所在位置\
	//遍历完没有合适的数字
	if
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值