最近在学习算法,看了图解算法,但是感觉写的太简单,理论比较多,代码实现比较和例子比较少,看完后,又接着看了《啊哈!算法》,这个感觉例子比较多,也比较适合我这种算法入门的读者。
书上的例子一一打了一遍,因为作者是用c写的,而我是没接触过c,用了自己比较熟悉的js把例子打了一遍。用广搜写了贪吃蛇自动吃果实,只能吃100多个,自认为还能完善,于是等完善后在放在博客上面吧。
这里先写写用dfs(深搜) 和 bfs(广搜)算法实现 炸弹人的统计哪个点能消灭的怪物最多的算法
这里是地图,要求从3,3位置走,在那个地方消灭的怪物最多
这里是用bfs 完成目标的算法 ,基本上都有注释
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>炸弹人</title>
</head>
<body>
<script>
function note(x,y){
this.x = x;
this.y = y;
}
var a = [
["#","#","#","#","#","#","#","#","#","#","#","#","#"],//1
["#","G","G",".","G","G","G","#","G","G","G",".","#"],//2
["#","#","#",".","#","G","#","G","#","G","#","G","#"],//3
["#",".",".",".",".",".",".",".","#",".",".","G","#"],//4
["#","G","#",".","#","#","#",".","#","G","#","G","#"],//5
["#","G","G",".","G","G","G",".","#",".","G","G","#"],//6
["#","G","#",".","#","G","#",".","#",".","#",".","#"],//7
["#","#","G",".",".",".","G",".",".",".",".",".","#"],//8
["#","G","#",".","#","G","#","#","#",".","#","G","#"],//9
["#",".",".",".","G","#","G","G","G",".","G","G","#"],//10
["#","G","#",".","#","G","#","G","#",".","#","G","#"],//11
["#","G","G",".","G","G","G","#","G",".","G","G","#"],//12
["#","#","#","#","#","#","#","#","#","#","#","#","#"]//13
];
//计算当前点能炸多少个怪物
function getnum(i,j){
var sum, x,y;
sum = 0;//sum用来计数(可以消灭的敌人数),所以需要初始化为0
//将坐标i,j复制到两个新变量中,以便之后向上下左右四个方向统计可以被消灭的敌人的数目
//向上统计可以消灭的敌人的数目
x = i;
y = j;
while(a[x][y]!="#"){//判断的点是不是墙,如果不是墙就继续
if(a[x][y]=="G"){
sum++;
}
//x--的作用是继续向上统计
x--;
}
//向下统计可以消灭的敌人数
x = i;
y = j;
while(a[x][y]!="#"){
if(a[x][y]=="G")
{
sum++;
}
//x++向下统计
x++;
}
//向左统计可以消灭的敌人数
x = i;
y = j;
while(a[x][y]!="#"){
if(a[x][y]=="G")
{
sum++;
}
//x++向下统计
y--;
}
//向右统计可以消灭的敌人数
x = i;
y = j;
while(a[x][y]!="#"){
if(a[x][y]=="G")
{
sum++;
}
//x++向下统计
y++;
}
return sum;
}
var que = [];
//假设地图大小不超过20*20,因此队列扩展不超过400个
var head,tail;
var book = [];
//初始化标记数组 为0;
for(var i = 1;i<=20;i++ ){
var now = [];
for(var j = 1;j<=20;j++){
now[j] = 0;
}
book[i] = now;
}
var i, j, k,sum,max= 0,mx,my, n, m,startx,starty,tx,ty;
//定义一个用于表示走的方向的数组 数组和坐标的表现方法正好相反
var next = [[0,1],//向右走
[1,0],//向下走
[0,-1],//向左走
[-1,0]];//向上走
//表示有多少行字符,m表示有多少列字符
n = 13;
m = 13;
//给小人的坐标赋值
startx = 3;
starty = 3;
//队列初始化
head = 1;
tail = 1;
//向初始队列中插入小人的坐标
que[tail] = new note();
que[tail].x = startx;
que[tail].y = starty;
//保证初始的tail比head大于,也就是head是tail队列的上一个元素
tail++;
//开始点设置为1
book[startx][starty]=1;
//先把初始点的数量赋值给max
max = getnum(startx,starty);
mx = startx;
my = starty;
//接下来便是扩展,也就是深度优先搜索的核心
//当队列不为空时循环
while(head<tail){
//枚举四个方向
for(k=0;k<=3;k++){
//尝试走下一个点
tx = que[head].x + next[k][0];
ty = que[head].y + next[k][1];
//判断是否越界
if(tx<0||tx>n-1||ty<0||ty>m-1){
continue;
}
//判断是否为平地或者曾经走过的
if(a[tx][ty]=="."&&book[tx][ty]==0){
//每个点只入队一次,所以要标记这个点已经走过
book[tx][ty]=1;
//插入新扩展的点到队列中
que[tail] = new note();
que[tail].x = tx;
que[tail].y = ty;
tail++;
sum =getnum(tx,ty);
if(sum>max){
//如果当前统计出的数目大于max,那么跟新max,并用mx,my记录该点的坐标
max = sum;
mx = tx;
my = ty;
}
}
}
head++;
}
console.log("坐标是:("+mx+","+my+")消灭的最大数量为:"+max);
</script>
</body>
</html>
这里是深搜实现的方法
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>炸弹人</title>
</head>
<body>
<script>
function note(x,y){
this.x = x;
this.y = y;
}
var a = [
["#","#","#","#","#","#","#","#","#","#","#","#","#"],//1
["#","G","G",".","G","G","G","#","G","G","G",".","#"],//2
["#","#","#",".","#","G","#","G","#","G","#","G","#"],//3
["#",".",".",".",".",".",".",".","#",".",".","G","#"],//4
["#","G","#",".","#","#","#",".","#","G","#","G","#"],//5
["#","G","G",".","G","G","G",".","#",".","G","G","#"],//6
["#","G","#",".","#","G","#",".","#",".","#",".","#"],//7
["#","#","G",".",".",".","G",".",".",".",".",".","#"],//8
["#","G","#",".","#","G","#","#","#",".","#","G","#"],//9
["#",".",".",".","G","#","G","G","G",".","G","G","#"],//10
["#","G","#",".","#","G","#","G","#",".","#","G","#"],//11
["#","G","G",".","G","G","G","#","G",".","G","G","#"],//12
["#","#","#","#","#","#","#","#","#","#","#","#","#"]//13
];
//计算当前点能炸多少个怪物
function getnum(i,j){
var sum, x,y;
sum = 0;//sum用来计数(可以消灭的敌人数),所以需要初始化为0
//将坐标i,j复制到两个新变量中,以便之后向上下左右四个方向统计可以被消灭的敌人的数目
//向上统计可以消灭的敌人的数目
x = i;
y = j;
while(a[x][y]!="#"){//判断的点是不是墙,如果不是墙就继续
if(a[x][y]=="G"){
sum++;
}
//x--的作用是继续向上统计
x--;
}
//向下统计可以消灭的敌人数
x = i;
y = j;
while(a[x][y]!="#"){
if(a[x][y]=="G")
{
sum++;
}
//x++向下统计
x++;
}
//向左统计可以消灭的敌人数
x = i;
y = j;
while(a[x][y]!="#"){
if(a[x][y]=="G")
{
sum++;
}
//x++向下统计
y--;
}
//向右统计可以消灭的敌人数
x = i;
y = j;
while(a[x][y]!="#"){
if(a[x][y]=="G")
{
sum++;
}
//x++向下统计
y++;
}
return sum;
}
function dfs(x,y){
var next = [[0,1],//向右走
[1,0],//向下走
[0,-1],//向左走
[-1,0]];//向上走
var k,sum,tx,ty;
//计算当前点所消灭的敌人
sum = getnum(x,y);
//更新max的值和坐标
if(sum>max){
max = sum;
mx = x;
my = y;
}
//枚举四个方向
for(k = 0;k<=3;k++){
//下一个点的坐标
tx = x + next[k][0];
ty = y + next[k][1];
//判断是否出局
if(tx<0||tx>n-1||ty<0||ty>m-1){
continue;
}
//判断是否可走 并且没有被标记过
if(a[tx][ty]=="."&&book[tx][ty]==0){
//更新标记
book[tx][ty] = 1;
//开始尝试走下一个点
dfs(tx,ty);
}
}
//返回到上一个方法
return;
}
var i,startx,starty,max,mx,my;
//初始化记录队列
var book = [];
//初始化标记数组 为0;
for(var i = 1;i<=20;i++ ){
var now = [];
for(var j = 1;j<=20;j++){
now[j] = 0;
}
book[i] = now;
}
//表示有多少行字符,m表示有多少列字符
n = 13;
m = 13;
//给小人的坐标赋值
startx = 3;
starty = 3;
//开始点设置为1
book[startx][starty]=1;
//先把初始点的数量赋值给max
max = getnum(startx,starty);
mx = startx;
my = starty;
dfs(startx,starty);
console.log("坐标是:("+mx+","+my+")消灭的最大数量为:"+max);
</script>
</body>
</html>
答案应该是下面的