第五天
回溯法:
回溯跟递归都是程序员考试里常出现的问题,大家必须掌握!
回溯法的有关概念:
1) 解答树:叶子结点可能是解,对结点进行后序遍历.
2) 搜索与回溯
五个数中任选三个的解答树(解肯定有三层,至叶子结点):
ROOT 虚根
/ / | \ \
1 2 3 4 5
/ | | \ / | \ /\ |
2 3 4 5 3 4 5 4 5 5
/|\ /\ | /\ | |
3 4 5 4 5 5 4 5 5 5
回溯算法实现中的技巧:栈
要搞清回溯算法,先举一个(中序遍历二叉树的非递归算法)来说明栈在非递归中所起的作用。
A 过程:push()->push()->push()->push()栈内结果:ABDE(E为叶子,结束进栈)
/ \ pop() ABD(E无右孩子,出栈)
B C pop() AB(D无右孩子,出栈)
/\ pop() A(B有右孩子,右孩子进栈)
D F . .
/ /\ . .
E G H . .
/ . .
I 最后结果: EDBGFIHAC
简单算法:
…
if(r!=NULL) //树不空
{ while(r!=NULL)
{ push(s,r);
r=r->lch; //一直向左孩子前进
}
while(!empty(s)) // 栈非空,出栈
{ p="pop"(s);
printf(p->data);
p=p->rch; //向右孩子前进
while(p!=NULL)
{ push(s,p);
p=p->lch; //右孩子进栈
}
}
} //这就是传说中的回溯,嘻嘻……没吓着你吧
5选3问题算法:
思想: 进栈:搜索
出栈:回溯
边建树(进栈)边遍历(出栈)
基本流程:
太复杂了,再说我不太喜欢用WORD画图(有损形象),以后再整理!
程序: n="5";r=3
……
init(s) //初始化栈
push(s,1) //根进栈
while(s.top push(s,s.data[s.top]+1); //孩子入栈
while(!empty(s))
{ if(s.top=r-1)
判断该"解"是否为解.
x=pop(s); //保留x,判断是否为最大值n,如果是n,则出栈
while(x==n)
x=pop(s);
push(s,x+1);
while(s.top push(s,s.data[s.top]+1);
}
背包问题: TW="20" , w[5]={6,10,7,5,8}
解的条件:1) 该解答树的叶子结点
2) 重量最大
解答树如下: ROOT
/ | | | \
6 10 7 5 8
/ | | \ / | \ / \ |
10 7 5 8 7 5 8 5 8 8
| | |
5 8 8
程序:
temp_w 表示栈中重量和
…
init(s); //初始化栈
i=0;
While(w>TW)
i++;
If(i==n) Return -1; //无解
Else {
Push(s,i);
Temp_w=w;
i++;
while(i { push(s,i);
temp_w+=w;
i++;
}
max_w=0;
while(!empty(s))
{ if(max_w max_w=temp_w;
x=pop(s);
temp_w-=w[x];
x++;
while(xTW)
x++;
while(x { push(s,x);
temp_w=temp_w+w[x];
x++;
while(xTW)
x++;
}
}
请大家思考:四色地图问题,比如给中国地图涂色,有四种颜色,每个省选一种颜色,相邻的省不能取同样的颜色.不许偷懒,不能选人口不多于xxxxW的"大国"哦!如果真的有一天台湾独立了,下场就是这样了,一种颜色就打发了,不过台湾的程序员们赚到了,省事!呵呵。
贪婪法:
不求最优解,速度快(以精确度换速度)
例:哈夫曼树,最小生成树
装箱问题:
有n个物品,重量分别为w[n],要把这n个物品装入载重为TW的集装箱内,需要几个集装箱?
思想1:对n个物品排序
拿出第1个集装箱,从大到小判断能不能放。
2 …
3 …
. …
. …
思想2: 对n个物品排序
用物品的重量去判断是否需要一只新箱子,如果物品重量小于本箱子所剩的载重量,则装进去,反之则取一只新箱子。
程序:
count=1;qw[0]=TW;
for(i=0;i {
k=0;
while(kqw[k])
k++;
if(w<=qw[k])
qw[k]=qw[k]-w;
code=k; //第i个物品放在第k个箱子内
else
{count++; //取一个新箱子
qw[count-1]=TW-w;
code=count-1;
}
}
用贪婪法解背包问题:
n个物品,重量:w[n] 价值v
背包限重TW,设计一个取法使得总价值最大.
方法:
0 1 2 3 … n-1
w0 w1 w2 w3 … wn-1
v0 v1 v2 v3 … vn-1
v0/w0 … v(n-1)/w(n-1) 求出各个物品的"性价比"
先按性价比从高到低进行排序
已知:w[n],v[n],TW
程序:
…
for(I=1;I d=v/w; //求性价比
for(I=0;I { max="-1";
for(j=0;j { if(d[j]>max)
{ max="d"[j];x=j; }
}
e=x;
d[x]=0;
}
temp_w=0;temp_v=0;
for(i=0;i { if(temp_w+w[e]<=TW)
temp_v=temp_v+v[e[v]];
}
分治法:
思想:把规模为n的问题进行分解,分解成几个小规模的问题.然后在得到小规模问题的解的基础上,通过某种方法组合成该问题的解.
例:数轴上有n个点x[n],求距离最小的两个点.
分:任取一点,可以把x这n个点分成两个部分
小的部分 分点 大的部分
|_._.__.__.____._|__._._.__._.__._______._.__._._.__.___._____._|
治:解=min{小的部分的距离最小值;
大的部分的距离最小值;
大的部分最小点和小的部分最大点这两点之差;}
文章评论(0条评论)
登录后参与讨论