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