最优路径的一种算法(原创)
问题来自博问:http://q.cnblogs.com/q/28763/
给定的测试矩阵:
测试矩阵数据
- public int[,] InitMap()
- {
- //x-1,??-2,??-3,??????
- return new int[Width,Height]
- {
- {-2, 1, 5, 2, 4, 5, 8, 2, 1},
- {1, 5, 2, 4, 5, 8, 2, -1, 5},
- {2, 7, 5, 2, 4, 5, -1, 2, 1},
- {2, 1, 3, 2, -1, 0, 8, 7, 3},
- {2, 1, 5, 1, 9, 5, 2, 2, 1},
- {4, 8, 4, 3, 4, 2, 8, 2, 3},
- {2, 1, 5, 6, 4, 5, 7, 4, 1},
- {2, 8, 7, 2, 4, 5, 8, 2, 1},
- {1, 5, 5, 4, 5, 6, 2, 2, -3}
- };
- }
递归路径查找:
Code Snippet
- public bool NextStep(int x,int y )
- {
- if (x < 0 || x >=Width)
- return false;
- if(y<0||y>=Height)
- return false;
- //?????????1
- if(CurRoad.Count==KKCatStep+1)
- return false;
- int curScore = map[x, y];
- //?
- if(curScore==-1)
- return false;
- //??????
- if (CurRoad.Any(c => c.X == x && c.Y == y))
- return false;
- CurRoad.Push(new Coord(x,y));
- //?????????
- if (curScore == -3)
- {
- var score = CurRoad.Skip(1).Take(CurRoad.Count - 2).Sum(c => map[c.X, c.Y]);
- if(score>LastScore)
- {
- LastScore = score;
- var road = CurRoad.ToList();
- road.Reverse();
- NiceRoads.Add(road);
- }
- return true;
- }
- //???
- if (NextStep(x + 1, y))
- CurRoad.Pop();
- if(NextStep(x, y + 1))
- CurRoad.Pop();
- if(NextStep(x - 1, y))
- CurRoad.Pop();
- if(NextStep(x, y - 1))
- CurRoad.Pop();
- return true;
- }
效率还不是很高,特别对更大的地图时算法还有待优化。
以下是完整的代码:
Code Snippet
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- using Xunit;
- namespace KKCatWalking
- {
- public class Walking
- {
- protected int[,] map;
- const int Width= 9, Height = 9;
- private Stack<Coord> CurRoad = new Stack<Coord>();
- private List<List<Coord>> NiceRoads = new List<List<Coord>>();
- private int KKCatStep = 19;
- private int LastScore=0;
- public Walking()
- {
- map = InitMap();
- }
- [Fact]
- public void FindWays()
- {
- NextStep(0, 0);
- NiceRoads.TrimExcess();
- Console.WriteLine("KKCatStep:{0}\tTotal Roads:{1} MaxScore:{2}",KKCatStep,NiceRoads.Count,NiceRoads.Max(r=>r.Skip(1).Take(r.Count-2).Sum(c=>map[c.X,c.Y])));
- foreach(var r in NiceRoads.OrderByDescending(r=>r.Skip(1).Take(r.Count-2).Sum(c=>map[c.X,c.Y])).Take(20))
- {
- int sum = 0;
- foreach (var c in r)
- {
- Console .Write("{0},{1}\t",c.X,c.Y);
- sum += map[c.X, c.Y];
- }
- Console.WriteLine("Score:{0}\t", sum+5);
- Console.WriteLine();
- }
- }
- public bool NextStep(int x,int y )
- {
- if (x < 0 || x >=Width)
- return false;
- if(y<0||y>=Height)
- return false;
- //?????????1
- if(CurRoad.Count==KKCatStep+1)
- return false;
- int curScore = map[x, y];
- //?
- if(curScore==-1)
- return false;
- //??????
- if (CurRoad.Any(c => c.X == x && c.Y == y))
- return false;
- CurRoad.Push(new Coord(x,y));
- //?????????
- if (curScore == -3)
- {
- var score = CurRoad.Skip(1).Take(CurRoad.Count - 2).Sum(c => map[c.X, c.Y]);
- if(score>LastScore)
- {
- LastScore = score;
- var road = CurRoad.ToList();
- road.Reverse();
- NiceRoads.Add(road);
- }
- return true;
- }
- //???
- if (NextStep(x + 1, y))
- CurRoad.Pop();
- if(NextStep(x, y + 1))
- CurRoad.Pop();
- if(NextStep(x - 1, y))
- CurRoad.Pop();
- if(NextStep(x, y - 1))
- CurRoad.Pop();
- return true;
- }
- public int[,] InitMap()
- {
- //x-1,??-2,??-3,??????
- return new int[Width,Height]
- {
- {-2, 1, 5, 2, 4, 5, 8, 2, 1},
- {1, 5, 2, 4, 5, 8, 2, -1, 5},
- {2, 7, 5, 2, 4, 5, -1, 2, 1},
- {2, 1, 3, 2, -1, 0, 8, 7, 3},
- {2, 1, 5, 1, 9, 5, 2, 2, 1},
- {4, 8, 4, 3, 4, 2, 8, 2, 3},
- {2, 1, 5, 6, 4, 5, 7, 4, 1},
- {2, 8, 7, 2, 4, 5, 8, 2, 1},
- {1, 5, 5, 4, 5, 6, 2, 2, -3}
- };
- }
- public struct Coord
- {
- public Coord(int x,int y)
- {
- X = x;
- Y = y;
- }
- public int X;
- public int Y;
- }
- }
- public enum MapEnum
- {
- Hole = -1,
- Start = -2,
- End = -3
- }
- }