如何理解回溯算法?
如果一个问题能够变成问题状态搜索树,那么深搜的过程就是用回溯求解的过程。
做法:1.先写出问题状态搜索树。
2.先实现再优化。
例题1:八皇后问题:
我们就按行顺序取图上这些棋子的坐标,发现:
这就是在求排列形枚举。不同的是,有一些排列要舍去(还要满足对角线)
先贴上原来的代码:
void Print(int n,int cur){
if(cur==n+1) {
for (int i = 1; i <= n; i++)printf("%d", ans[i]);
printf("\n");return;
}
for(int i=1;i<=n;i++){
if(!vis[i]){
ans[cur]=i;
vis[i]=1;
Print(n,cur+1);
vis[i]=0;
}
}
}
优化①:状态压缩:在输出全排列数组的时候,我们使用了一个vis数组,vis【i】=1代表i元素被占用了。可以用一个二进制数代替这个数组。这样把数组用数字替代。
优化②:快速枚举:
之前枚举的时候,是对所有i从1到n枚举,其中也包括一些已经被占用了的数字。由此我们想到,可以用位运算,直接取二进制数字最小的非0位置。(方法,x&(-x),可以证明求得的就是x不为0的最小位权)然后枚举完后,再用x-=x&(-x)
优化③:斜边表示:
本题其实是有限制版本的”全排列枚举“。我们发现x+y-1=i,表示在第i条正邪斜边的棋子,所以只要多取两个二进制数即可。
例题2:
优化1:剪枝操作:对每一个节点,我们假设中间有一点C,假设现在已知A-->C只用x步;那么当我们发现有一种方法是A-->C用x+1步时,就没有遍历的必要了。因为它不可能是最优解。由此判断。
例题3:马的遍历
本题有点类似二维的例题二。
优化1:本题每个点马会有八个选择,用方向数组表示:
例题4:迷宫
变成技巧:扩展棋盘+合法化
这样可以同时实现1.判断障碍物。2.判断坐标是否合法 3.判断是否走过一次
例题5:
优化1:分析问题搜索树:
又是排列形枚举!!所以优化1肯定是状态压缩。
优化2:搜索过程剪枝:
对于形如这样的两组(最后的终点都一样,且到目前为止的效果都一样),可以根据值的大小舍去。所以我们想到用一个dp【】【】数组,dp[t][6]代表第t个效果,6代表末尾位置是6.
#include<bits/stdc++.h>
using namespace std;
double x[20],y[20];
double dis[20][20];
double dp[70000][20];//dp用来记录状态
double ans=1e6;
double p_dis(int p1,int p2){
return sqrt((x[p1]-x[p2])*(x[p1]-x[p2])+(y[p1]-y[p2])*(y[p1]-y[p2]));
}
void dfs(int t1,int now,double s){//t1是状态码,s是当前的距离。
if(t1==0){
if(s<ans)ans=s;
return;
}//如果已经拍完了。
for(int k=t1;k;k-=(k&-k)){
int t=(k&-k);int to=0;
while(1){
if(1<<to==t)break;
to++;//to就是当前吃掉的奶酪编号
}
int next=t1-(1<<to);//吃掉to后的状态码
if(dp[next][to]!=0&&dp[next][to]<s+dis[now][to])continue;
dp[next][to]=s+dis[now][to];
if(ans<s+dis[now][to])continue;
dfs(next,to,s+dis[now][to]);
}
}
int main(){
int n;
scanf("%d",&n);
x[0]=y[0]=0;
for(int i=1;i<=n;i++){
scanf("%lf %lf",&x[i],&y[i]);
}
for(int i=0;i<=n;i++){
for(int j=i;j<=n;j++){
dis[i][j]=dis[j][i]=p_dis(i,j);//计算出个距离
}
}
dfs(((1<<(n+1))-2),0,0);
printf("%.2f",ans);
return 0;
}
思考本题要解决的问题:
1,扩展路径判断:存在重叠部分
2.维护龙的长度:
1.2可用预处理d【x】【y】表示两单词x,y重叠长度。用L+LEN(Y)-d【x】【y】
3.控制单词使用次数:可用一个vis数组表示使用次数。(注意回溯时候要减去使用次数)
例题6:拆分自然数:
问题搜索树:
优化1:定义拆分数字要逐渐增大。
优化2:判断拆分可行性
dfs(层号,可以使用的起始数字,还剩下的数字)