《算法笔记》4.3小节——算法初步->递归
先考虑边界,再考虑递归
1、全排列
#include <cstdio>
const int maxn = 11;
int p[maxn], hashTable[maxn] = { false };
//从index到n的全排列
void generateP(int index,int n) {
if (index == n + 1) { //递归边界,已经处理完1-n位
for (int i = 1; i <= n; i++)
printf("%d", p[i]);
printf("\n");
return;
}
for (int x = 1; x <= n; x++) {
if (hashTable[x] == false) { //x不在p[0]-p[index-1]中,放入第inedx位
p[index] = x;
hashTable[x] = true;
generateP(index + 1,n); //处理排列的第index+1位
hashTable[x] = false; //已处理完p[index]为x的子问题,还原状态
}
}
}
int main() {
int n;
scanf("%d", &n);
generateP(1,n);
return 0;
}
2、n皇后问题
暴力法:枚举+判断
#include <cstdio>
#include <cstring>
#include <cstdlib>
const int maxn = 11000;
int count = 0;
int p[maxn], hashTable[maxn] = { false };
void generateP(int index,int n) {
if (index == n + 1) {
bool flag = true;
for (int i = 0; i < n; i++) {
for (int j = i+1; j < n; j++) { //往后比即可
//if ((i + p[i]) == (j + p[j])) flag == false;
if (abs(i - j) == abs(p[i] - p[j])) flag = true;
}
}
if (flag) count++;
return;
}
for (int x = 1; x <= n; x++) {
if (hashTable[x] == false) { //x不在p[0]-p[index-1]中,放入第inedx位
p[index] = x;
hashTable[x] = true;
generateP(index + 1,n); //处理排列的第index+1位
hashTable[x] = false; //已处理完p[index]为x的子问题,还原状态
}
}
}
int main() {
int n;
scanf("%d", &n);
generateP(1,n);
printf("%d", count);
return 0;
}
回溯法:递归到某层时(达到边界前),发现不符合,则直接返回上一层
(代码貌似有问题)
#include <cstdio>
#include <cstring>
#include <cstdlib>
const int maxn = 11000;
int count = 0;
int p[maxn], hashTable[maxn] = { false };
void generateP(int index, int n) {
if (index == n + 1) {
count++; //能到达边界的一定是合法的
return;
}
for (int x = 1; x <= n; x++) {
if (hashTable[x] == false) { //x不在p[0]-p[index-1]中,放入第inedx位
bool flag = true;
for (int pre = 1; pre < index; pre++) {
if (abs(index - pre) == abs(x - p[pre])) {
flag = false; //与之前的皇后在同一条对角线,冲突
break;
}
}
if (flag) {
p[index] = x;
hashTable[x] = true;
generateP(index + 1, n);
hashTable[x] = false;
}
}
}
}
int main() {
int n;
scanf("%d", &n);
generateP(1,n);
printf("%d", count);
return 0;
}
1907 Problem A 吃糖果
#include <cstdio>
#include <cstring>
int cnt = 0;
void choc(int n) {
if (n == 0) {
cnt++;
return;
}
else {
if (n == 1) {
n -= 1;
choc(n);
}
else {
for (int i = 1; i <= 2; i++) {
choc(n - i);
}
}
}
}
int main() {
int n;
while (scanf("%d", &n) != EOF) {
cnt = 0;
choc(n);
printf("%d\n", cnt);
}
return 0;
}
2018 Problem B 数列
#include <cstdio>
#include <cstring>
int cnt = 0;
int fib(int n) {
if (n == 0) return 0;
else if (n == 1) return 1;
else return(fib(n - 1) + fib(n - 2));
}
int main() {
int n;
scanf("%d", &n);
while (n--) {
int m;
scanf("%d", &m);
for (int i = 0; i < m; i++) {
for (int k = 0; k < 2 * (m - i - 1); k++)
printf(" ");
for (int j = 0; j < (2*i+1); j++) {
printf("%d", fib(j));
if (j != (2 * i)) printf(" ");
}
printf("\n");
}
}
return 0;
}
2044 Problem C 神奇的口袋
#include <cstdio>
#include <cstring>
int count, n, a[25];
void select(int index,int sum) {
if (sum == 0) {
count++;
return;
}
else if ( index >= n)
return;
if (sum - a[index] >= 0) {
select(index + 1, sum - a[index]); //选中该元素
}
select(index+1, sum); //未选中该元素
}
int main() {
while (scanf("%d", &n)!=EOF) {
count = 0;
for (int i = 0; i < n; i++) {
scanf("%d", &a[i]);
}
select(0, 40);
printf("%d\n", count);
}
return 0;
}
2046 Problem D 八皇后
在这里插入代码片