回溯算法解题套路框架https://labuladong.gitbook.io/algo/suan-fa-si-wei-xi-lie/3.1-hui-su-suan-fa-dfs-suan-fa-xi-lie/hui-su-suan-fa-xiang-jie-xiu-ding-ban
result = []
def backtrack(路径, 选择列表):
if 满足结束条件:
result.add(路径)
return
for 选择 in 选择列表:
做选择
backtrack(路径, 选择列表)
撤销选择
全排列代码分两个,一个是遍历+标记(root的),另一个是交换(高效的)
#include <iostream>
#include<bits/stdc++.h>
using namespace std;
int fin=4;
int res[15]={0};
int a[11]={0};
void trackback(int n)
{
if(fin==n)
{
for(int i=1;i<=fin;i++)
{
if(a[i]==0)
{
res[n]=i;
/// a[i]=1;这句绝对不能加,不然会少---因为没有能置回的
// cout<<"*";
}
}
//output
for(int i=1;i<=fin;i++)
{
cout<<res[i]<<" ";
}
cout<<endl;
return ;
}
///
for(int i=1;i<=fin;i++)///每次都要遍历生成,所以效率低
{
if(a[i]==1)
{
continue;
}
///xuanze
res[n]=i;
a[i]=1;
trackback(n+1);
///fuyuan
a[i]=0;
}
}
int res2[100];
void trackback2(int m)
{
if(m==fin+1)
{
for(int i=1;i<=fin;i++)
{
cout<<res2[i]<<" ";
}
cout<<endl;
return ;
}
for(int i=m;i<=fin;i++)
{
swap(res2[m],res2[i]);
trackback2(m+1);
swap(res2[i],res2[m]);///这里m i 也不影响结果
}
}
int main()
{
//trackback(1);
for(int i=1;i<=fin;i++)
{
res2[i]=i;
}
trackback2(1);
// int x=1,y=2;
// swap(x,y);
// cout<<x<<y;///out 2 1
return 0;
}
全排列复习代码2021.3.9—用的fin<n的条件,可以省一遍代码
#include <iostream>
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int fin=4;
int res[15]={0};
int a[10]={0};
void out()
{
for(int i=1;i<=fin;i++)
{
cout<<res[i]<<" ";
}
cout<<endl;
}
void traceback(int n)
{
if(fin<n)
{
out();
return;
}
for(int i=1;i<=4;i++)
{
if(a[i]==1)continue;
a[i]=1;
res[n]=i;
traceback(n+1);
a[i]=0;
}
return ;
}
int main()
{
traceback(1);
return 0;
}
2021.4.17记得return啊
#include <iostream>
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define maxn 10005
int fin=5;///0~5 选5个数
int a[maxn];
int result[maxn];
void backtrack(int n)
{
if(n>fin)
{
for(int i=1;i<=fin;i++)
{
cout<<result[i];
}
cout<<endl;
///这里应该return
return;
}
for(int i=0;i<=fin;i++)
{
if(a[i]==1)continue;
result[n]=i;
a[i]=1;
backtrack(n+1);
a[i]=0;
}
}
int main()
{
backtrack(1);
return 0;
}
N皇后
这个问题很经典了,简单解释一下:给你一个 N×N 的棋盘,让你放置 N 个皇后,使得它们不能互相攻击。
PS:皇后可以攻击同一行、同一列、左上左下右上右下四个方向的任意单位。
这个问题本质上跟全排列问题差不多,决策树的每一层表示棋盘上的每一行;每个节点可以做出的选择是,在该行的任意一列放置一个皇后。
#include <iostream>
#include<bits/stdc++.h>
using namespace std;
int res[1000][1000]={0};
int fin=8;
int sum=0;
int isValid(int row,int col)
{
for(int i=1;i<=fin;i++)
{
if(res[i][col]==1)
{
return 0;
}
}
for(int i=row-1,j=col+1;i>=0&&j<=fin;i--,j++)
{
if(res[i][j]==1)
{
return 0;
}
}
for(int i=row-1,j=col-1;i>=0&&j>=0;i--,j--)
{
if(res[i][j]==1)
{
return 0;
}
}
return 1;
}
void trackback(int row)
{
if(row>fin)
{
for(int i=1;i<=fin;i++)
{
for(int j=1;j<=fin;j++)
{
cout<<res[i][j]<<" ";
}
cout<<endl;
}
cout<<endl;
sum++;
return ;
}
///
for(int col=1;col<=fin;col++)
{
if(!isValid(row,col))
continue;
///
res[row][col]=1;
trackback(row+1);
res[row][col]=0;
}
}
int main()
{
trackback(1);
cout<<"sum="<<sum<<endl;
return 0;
}