1、深度优先递归遍历
/*
*深度优先递归遍历[不重复的数字顺序排列组合]
*@param $step 第几步
*@param $a 数组
*@param $book 标记
*@param $num 统计总数
*/
function dfs($step,$a,$book,&$num){
if($step==6+1){//到临界点终止
for($i=1;$i<=6;$i++){
print_r($a[$i]).' ';
}
print_r('<br>');
$num++;
return;
}
for($i=1;$i<=6;$i++){
if(!isset($book[$i])||$book[$i]==0){
$a[$step] = $i;//表示第$step步选择了$i号
$book[$i] = 1;//标记$i号已选择
dfs($step+1,$a,$book,$num);//递归下一步
$book[$i] = 0;//收回$i号,重新选择
}
}
}
$num = 0;
dfs(1,array(),array(),$num);
2、广度优先遍历
class Node{
public $x;
public $y;
public $f;
public $step;
}
$queue = array();
$num = 0;
$next = array(
0 => array(0,1),
1 => array(1,0),
2 => array(0,-1),
3 => array(-1,0)
);
$migong = array(
0 => array(0,0,1,0),
1 => array(0,0,0,0),
2 => array(0,0,1,0),
3 => array(0,1,0,0),
4 => array(0,0,0,1)
);
$start_x = 0;
$start_y = 0;
$step = 0;
$destination_x = 3;
$destination_y = 2;
$p = new Node();
$p->x = $start_x;
$p->y = $start_y;
$p->f = 0;
$p->step = 0;
$queue[] = $p;
$book[$start_x][$start_y] = 1;
$flag = 0;
$head = 0;
$tail = 1;
//print_r($queue);
while($head<$tail){
for($k=0;$k<=3;$k++){
$tx = $queue[$head]->x+$next[$k][0];
$ty = $queue[$head]->y+$next[$k][1];
//判断越界
if($tx<0||$tx>4||$ty<0||$ty>3){
continue;
}
if($migong[$tx][$ty]==0&&(!isset($book[$tx][$ty])||$book[$tx][$ty]==0)){
print_r($tx.','.$ty.'<br>');
$book[$tx][$ty] = 1;
$q = new Node();
$q->x = $tx;
$q->y = $ty;
$q->f = $head;
$q->step = $queue[$head]->step+1;
$queue[$tail] = $q;
$tail++;
print_r($queue);
}
//到达目的地
if($tx==$destination_x&&$ty==$destination_y){
$flag = 1;
print_r('什么鬼'.$tx.'=='.$ty);
break;
}
}
if($flag==1)
break;
$head++;//当一个扩展结束后,head++才能对后面的点再进行扩展
print_r('head:'.$head.'==tail:'.$tail.'<br>');
}
//$this->bfs($start_x,$start_y,$destination_x,$destination_y,$step);
print_r('step:'.$queue[$tail-1]->step);
$index = $tail-1;
$f_x = $queue[$index]->x;
$f_y = $queue[$index]->y;
while($f_x!==$start_x||$f_y!==$start_y){//打印路径
print_r('('.$f_x.','.$f_y.')<br>');
$index = $queue[$index]->f;
$f_x = $queue[$index]->x;
$f_y = $queue[$index]->y;
}
3、最短路径算法
Floyd-Warshall算法基本思想:最开始只允许经过1号顶点进行中转,接下来只允许经过1号和2号顶点进行中转~~~允许经过1-n号所有顶点进行中转,求任意两点之间的最短路程,其实是一种动态规划的思想。
for($k=1;$k<m;$k++){
for($i=1;$i<=m;$i++){
for($j+1;$j<=m;$j++){
if($e[$i][$j]>$e[$i][$k]+$e[$k][$j]){
$e[$i][$j] = $e[$i][$k]+$e[$k][$j];
}
}
}
}
单源最短路程算法(Dijkstra)基本思想:每次找到离源点最近的一个顶点,然后以该顶点为中心进行扩展,最终得到源点到其余所有点的最短路径。
基本步骤:
1、选一顶点v为源点,并视从源点v出发的所有边为到各顶点的最短路径(确定数据结构:因为求的是最短路径,所以①就要用一个记录从源点v到其它各顶点的路径长度数组dist[],开始时,dist是源点v到顶点i的直接边长度,即dist中记录的是邻接阵的第v行。②设一个用来记录从源点到其它顶点的路径数组path[],path中存放路径上第i个顶点的前驱顶点)。
2、在上述的最短路径dist[]中选一条最短的,并将其终点(即<v,k>)k加入到集合s中。
3、调整T中各顶点到源点v的最短路径。 因为当顶点k加入到集合s中后,源点v到T中剩余的其它顶点j就又增加了经过顶点k到达j的路径,这条路径可能要比源点v到j原来的最短的还要短。调整方法是比较dist[k]+g[k,j]与dist[j],取其中的较小者。
4、再选出一个到源点v路径长度最小的顶点k,从T中删去后加入S中,再回去到第三步,如此重复,直到集合S中的包含图G的所有顶点。
//核心算法
$inf = 99999;
for($i=1;$i<=n;$i++){
$book[i] = 0;
$dis[$i] = $e[1][$i];//1号顶点到其余各个顶点的初始路程
}
for($i=1;$i<=n-1;$i++){
//找到离1号顶点最近的顶点
$min = $inf;
for($j=1;$j<=n;$j++){
if($book[$j]==0 && $dis[$j]<$min){
$min = $dis[$j];
$u = $j;
}
}
$book[$u] = 1;
for($v=1;$v<=n;$v++){
if($e[$u][$v]<$inf){
if($dis[$v]>$dis[$u]+$e[$u][$v]){
$dis[$v] = $dis[$u]+$e[$u][$v];
}
}
}
}
Bellman-Ford算法(针对负权边):
for(k=1;k<=n-1;k++)//进行n-1轮松弛
for(i=1;i<=m;i++)//枚举每一条边
if(dis[v[i]] > dis[u[i]] + w[i])//尝试对每一条边进行松弛
dis[v[i]] = dis[u[i]] + w[i];