QQ超市最优路径寻路研究

应广大群众的要求,终于开始着手研究最优路径了。

其实最初一直认为,计算量太大,家用电脑的性能根本就无法实现。等真的做了之后才知道……

真的无法实现!!

何谓最优?以QQ超市的经营理念,应该满足如下要求:

  1.销售面数最大

  2.充分利用所有空间

  3.既要满足非RMB玩家的要求(全单面),又要满足RMB玩家的要求(多放双面和4面)

  4.单格货架、双格货架能合理搭配摆放在空位上。

基本上,除了第一点,其他都无法满足要求……

----------------------------------------------------

想了很久,基本思路:用穷举法找到所有路径,然后计算找出面数最大路径。

具体如下:

  1.用递归来实现,传入参数Point PointNow(当前位置) Dictionary<Point, Point> pathsNow(当前键值集合)

         学过寻路的都知道,键值集合存的是路径的父子关系,用于逆推路径。

     递归流程1:先判断当前位置是否终点,是则返回true

     递归流程2:循环当前位置四周4个方向的可用点。递归调用自己,判断结果是否终点。是则获取路径保存在路径总表里。

         ※ 流程2中可用点的判断:非界外、非障碍、非链表内、除入口外四周无路径(路径是不许接壤的)

  2.遍历路径总表,算出和所有路径接壤的空白位置数就等于面数,记录最大面数和该路径ID。

其中修修改改还加了很多避免错误和循环的判断。

写代码倒没花多少时间。成果是出来了,可是效率低得可怜。

1店4口碑之前还好,很快就算出来了。1店5口碑用了差不多1个小时,找出340万条路径,其中面数最大的有700多条。

5口碑地图大小为13*13。这个过程估计判断+计算都有3^(13*13)次……

5口碑往后的计算也没敢去弄了。目前据说最高都出了9口碑,大小估计有20*20,1个月都算不出结果。

再者,路径虽然能算出,但是单格双格货架这个元素无法加入判断,4~6店只有双格货架,算出的路径根本就无法满足要求。

只能放弃了。

部分代码如下,因为几百万条路径太耗内存,此代码中改为只保存最大面数的路径。

//目前位置搜索到的路径节点
private Dictionary<Point, Point> paths;//当前键值集合
private LinkedList<Point>[] pathList;//所有路径列表
public int pathListIndex=0;//路径列表index
public int totalPathNum = 0;//总路径数
public int maxFace = 0;//当前统计出的最大面数
public int maxFaceID = 0;//

public void research ()
{
paths=new Dictionary<Point,Point>();
pathList=new LinkedList<Point>[5000000];
pathListIndex = 0;
totalPathNum = 0;
maxFace = 0;
maxFaceID = 0;
//paths.Add(startTile, startTile);
searchAll(startTile, paths);
}

//寻找所有路径
private bool searchAll(Point PointNow, Dictionary<Point, Point> pathsNow)
{
if (PointNow == endTile)//当前点为终点返回true
{
return true;
}
foreach (Point point in OpenMapTiles(PointNow))//遍历四周可走格子
{

if (!pathsNow.ContainsKey(point) && point != startTile)//如果此点不是路径和起点
{
bool a=true;
foreach (Point point1 in OpenMapTiles(point))//遍历该点四周可走格子
{
//当前点=起点 && 此格子!=当前点 && 此格子==路径
//当前点!=起点 && 此格子!=当前点 && (此格子==起点 || 此格子==路径)
if((PointNow==startTile && point1!=PointNow && pathsNow.ContainsKey(point1))||
(PointNow != startTile && point1 != PointNow && (point1 == startTile || pathsNow.ContainsKey(point1))))
a = false;
}
if (a)//如果符合
{
Dictionary<Point, Point> pathsNew =new Dictionary<Point, Point>();//定义新的集合和点,赋值
foreach (KeyValuePair<Point, Point> tmpKey in pathsNow)
pathsNew.Add(tmpKey.Key, tmpKey.Value);

Point pointNew=new Point( point.X,point.Y);

pathsNew[point] = PointNow;//串联路径 paths[当前坐标]=上一坐标
if (searchAll(pointNew, pathsNew))//如果此点为终点
{
LinkedList<Point> temList = FinalPath(pathsNew);//取得路径
int temFaceNum=faceNumTest(temList);//计算面数

totalPathNum ++;//总数+1
if (temFaceNum > maxFace)//如果大于当前最大面数,
{
maxFace = temFaceNum;
pathList = new LinkedList<Point>[5000000];//充值list,并保存当前路径
pathList[0] = temList;
pathListIndex = 1;
}
else if (temFaceNum == maxFace)//如果等于当前最大面数
{
pathList[pathListIndex] = FinalPath(pathsNew);//将路径付与路径列表
pathListIndex++;//数量+1
}

break;//只要有一个终点,代表此点临近终点,不用继续循环
}
}
}

}

return false;
}

//将路径取出放入双向链表
private LinkedList<Point> FinalPath(Dictionary<Point, Point> pathsNow)
{
LinkedList<Point> path = new LinkedList<Point>();//LinkedList 双向链表

Point curPrev = EndTile;//取终点
path.AddFirst(curPrev);//从链头插入

//从终点开始逆推paths路径并从path链头插入
while (pathsNow.ContainsKey(curPrev))//是否包含指定键,
{
curPrev = pathsNow[curPrev];
path.AddFirst(curPrev);
}
return path;
}

public void SetPathTest(int index)
{
foreach (Point point in pathList[index])//遍历并设置路径数值
{
if (mapTiles[point.X, point.Y] == MapTileType.MapEmpty)
mapTiles[point.X, point.Y] = MapTileType.MapPath;
}
for (int i = 0; i < floorList.Count; i++)
{
if (mapTiles[floorList[i].Position.X, floorList[i].Position.Y] == MapTileType.MapPath)
floorList[i].LightColor = new Vector3(0.5f, 1f, 0.5f);
else if (mapTiles[floorList[i].Position.X, floorList[i].Position.Y] == MapTileType.MapEmpty)
floorList[i].LightColor = new Vector3(1f, 1f, 1f);

}
}


//统计数据
public void StatDataTest()
{
maxFace = 0;
maxFaceID = 0;
for (int i = 0; i < pathListIndex; i++)//遍历路径表
{
int faceNum = 0;
foreach (Point point in pathList[i])//遍历当前路径所有坐标
{
foreach (Point point1 in OpenSpace(point))//遍历四周空格
{
if (!pathList[i].Contains(point1))
faceNum++;//面数+1
}
}
if (faceNum > maxFace)
{
maxFace = faceNum;//记录最大面数和ID
maxFaceID = i;
}


}

}
//统计数据
public int faceNumTest(LinkedList<Point> temList)
{
int faceNum = 0;
foreach (Point point in temList)//遍历当前路径所有坐标
{
foreach (Point point1 in OpenSpace(point))//遍历四周空格
{
if (!temList.Contains(point1))
faceNum++;//面数+1
}
}
return faceNum;
}
private bool IsOpenTest(int column, int row)
{
// 在图中&& 空地
return InMap(column, row) && (mapTiles[column, row] == MapTileType.MapEmpty ||
mapTiles[column, row] == MapTileType.MapPath);
}

public IEnumerable<Point> OpenSpace(Point mapLoc)//迭代器
{
if (IsOpenTest(mapLoc.X, mapLoc.Y + 1))
yield return new Point(mapLoc.X, mapLoc.Y + 1);
if (IsOpenTest(mapLoc.X, mapLoc.Y - 1))
yield return new Point(mapLoc.X, mapLoc.Y - 1);
if (IsOpenTest(mapLoc.X + 1, mapLoc.Y))
yield return new Point(mapLoc.X + 1, mapLoc.Y);
if (IsOpenTest(mapLoc.X - 1, mapLoc.Y))
yield return new Point(mapLoc.X - 1, mapLoc.Y);
}

 

posted @ 2012-03-16 20:09  妖気  阅读(847)  评论(0编辑  收藏  举报