题目
假定街道是棋盘型的,每格距离相等,车辆通过每格街道需要时间均为 timePerRoad;街道的街口(交叉点)有交通灯,灯的周期T(=lights[row][col])各不相同;车辆可直行、左转和右转,其中直行和左转需要等相应T时间的交通灯才可通行,右转无需等待。
现给出 n*m 个街口的交通灯周期,以及起止街口的坐标,计算车辆经过两个街口的最短时间。
其中:
1)起点和终点的交通灯不计入时间,且可以任意方向经过街口
2)不可超出 n*m 个街口,不可跳跃,但边线也是道路(即 lights[0][0] -> lights[0][1] 是有效路径)
入口函数定义:
/**
* lights : n*m 个街口每个交通灯的周期,值范围[0,120],n和m的范围为[1,9]
* timePerRoad : 相邻两个街口之间街道的通过时间,范围为[0,600]
* rowStart : 起点的行号
* colStart : 起点的列号
* rowEnd : 终点的行号
* colEnd : 终点的列号
* return : lights[rowStart][colStart] 与 lights[rowEnd][colEnd] 两个街口之间的最短通行时间
*/
int calcTime(int[][] lights,int timePerRoad,int rowStart,int colStart,int rowEnd,int colEnd)
输入描述
第一行输入 n 和 m,以空格分隔
之后 n 行输入 lights矩阵,矩阵每行m个整数,以空格分隔
之后一行输入 timePerRoad
之后一行输入 rowStart colStart,以空格分隔
最后一行输入 rowEnd colEnd,以空格分隔
输出描述
lights[rowStart][colStart] 与 lights[rowEnd][colEnd] 两个街口之间的最短通行时间
用例
输入
3 3
1 2 3
4 5 6
7 8 9
60
0 0
2 2
输出
245
说明
行走路线为 (0,0) -> (0,1) -> (1,1) -> (1,2) -> (2,2) 走了4格路,2个右转,1个左转,共耗时 60+0+60+5+60+0+60=245
以下是C++的非递归解法,递归虽然能解该题,但是实际项目过程中,好的编码规范一律不允许使用递归,因为它会带来非常多的不确定性隐患。
#include <stdio.h>
#include <map>
#include <vector>
#include <iostream>
#include <string>
using namespace std;
class CRoadPoint
{
public:
static void SetPointMax(unsigned int x, unsigned int y)
{
xMax = x;
yMax = y;
}
CRoadPoint(unsigned int x, unsigned int y,unsigned int uiWaitFromParent,bool bCorrect = false)
:m_uiWaitFromParent(uiWaitFromParent),m_pGamePointParent(NULL),m_bCorrectPoint(bCorrect)
{
if (x <= xMax && y <= yMax)
{
m_uiPointX= x;
m_uiPointY = y;
m_bCorrectPoint = true;
}
}
bool operator==(const CRoadPoint& oPointRight)
{
if(this->m_uiPointX == oPointRight.m_uiPointX && this->m_uiPointY == oPointRight.m_uiPointY)
{
return true;
}
return false;
}
string PointOutput()
{
char strTemp[100];
memset(strTemp,0x00,100);
sprintf(strTemp,"Point(x:%d,y:%d) ",m_uiPointX,m_uiPointY);
return strTemp;
}
string PointOutputToRoot()
{
string strOutPut = PointOutput();
CRoadPoint* pTemp = m_pGamePointParent;
while(pTemp != NULL)
{
strOutPut = pTemp->PointOutput() + strOutPut;
pTemp = pTemp->m_pGamePointParent;
}
return strOutPut;
}
unsigned int PointWaitToRoot()
{
unsigned int uiWait = m_uiWaitFromParent;
CRoadPoint* pTemp = m_pGamePointParent;
while(pTemp != NULL)
{
uiWait += pTemp->m_uiWaitFromParent;
pTemp = pTemp->m_pGamePointParent;
}
return uiWait;
}
bool IsNewPoint(const CRoadPoint& oNewPoint)
{
if (*this == oNewPoint)
{
return false;
}
bool bNewPoint(true);
CRoadPoint* pTemp = m_pGamePointParent;
while(pTemp != NULL)
{
if ((*pTemp) == oNewPoint)
{
bNewPoint = false;
break;
}
pTemp = pTemp->m_pGamePointParent;
}
return bNewPoint;
}
public:
CRoadPoint* m_pGamePointParent;
unsigned int m_uiPointX;
unsigned int m_uiPointY;
unsigned int m_uiWaitFromParent;
bool m_bCorrectPoint;
static unsigned int xMax;
static unsigned int yMax;
};
unsigned int CRoadPoint::xMax = 0;
unsigned int CRoadPoint::yMax = 0;
//入口函数定义:
/**
* lights : n*m 个街口每个交通灯的周期,值范围[0,120],n和m的范围为[1,9]
* timePerRoad : 相邻两个街口之间街道的通过时间,范围为[0,600]
* rowStart : 起点的行号
* colStart : 起点的列号
* rowEnd : 终点的行号
* colEnd : 终点的列号
* return : lights[rowStart][colStart] 与 lights[rowEnd][colEnd] 两个街口之间的最短通行时间
*/
int calcTime(int lights[][10],int timePerRoad,int rowStart,int colStart,int rowEnd,int colEnd)
{
CRoadPoint oPointStart(rowStart,colStart,0);
CRoadPoint oPointEnd(rowEnd,colEnd,0);
typedef vector<CRoadPoint> VectorGamePoint;
map<int,VectorGamePoint> mapFind;
VectorGamePoint vecPoint;
VectorGamePoint vecResult;
vecPoint.push_back(oPointStart);
mapFind[0] = vecPoint;
map<int,VectorGamePoint>::iterator iterMapFind = mapFind.end();
bool bFindBaby(false);
while (!bFindBaby)
{
iterMapFind = mapFind.end();
iterMapFind--;
VectorGamePoint vecPointTemp = iterMapFind->second;
VectorGamePoint vecNewPoin;
for (size_t sCurSize = 0 ; sCurSize < vecPointTemp.size();sCurSize++)
{
CRoadPoint oPointTemp = vecPointTemp[sCurSize];
if (oPointTemp == oPointEnd)
{
bFindBaby = true;
vecResult.push_back(oPointTemp);
continue;
}
else if (bFindBaby == false)
{
bool bEnable(false);
unsigned int uiWait = lights[oPointTemp.m_uiPointX][oPointTemp.m_uiPointY];
if (oPointTemp.m_uiPointX > 0)
{
//left
CRoadPoint oPointLeft(oPointTemp.m_uiPointX - 1,oPointTemp.m_uiPointY,uiWait);
oPointLeft.m_pGamePointParent = &((iterMapFind->second)[sCurSize]);
bool bEnable = oPointLeft.m_bCorrectPoint;
if (bEnable == true && oPointTemp.IsNewPoint(oPointLeft))
{
vecNewPoin.push_back(oPointLeft);
}
}
if (oPointTemp.m_uiPointX < CRoadPoint::xMax)
{
//right
CRoadPoint oPointRight(oPointTemp.m_uiPointX + 1,oPointTemp.m_uiPointY,0);
bool bEnable = oPointRight.m_bCorrectPoint;
oPointRight.m_pGamePointParent = &((iterMapFind->second)[sCurSize]);
if (bEnable == true && oPointTemp.IsNewPoint(oPointRight))
{
vecNewPoin.push_back(oPointRight);
}
}
if (oPointTemp.m_uiPointY < CRoadPoint::yMax)
{
//top
CRoadPoint oPointTop(oPointTemp.m_uiPointX,oPointTemp.m_uiPointY + 1,uiWait);
oPointTop.m_pGamePointParent = &((iterMapFind->second)[sCurSize]);
bool bEnable = oPointTop.m_bCorrectPoint;
if (bEnable == true && oPointTemp.IsNewPoint(oPointTop))
{
vecNewPoin.push_back(oPointTop);
}
}
if (oPointTemp.m_uiPointY > 0)
{
//Bottom
CRoadPoint oPointBottom(oPointTemp.m_uiPointX,oPointTemp.m_uiPointY - 1,uiWait);
oPointBottom.m_pGamePointParent = &((iterMapFind->second)[sCurSize]);
bool bEnable = oPointBottom.m_bCorrectPoint;
if (bEnable == true && oPointTemp.IsNewPoint(oPointBottom))
{
vecNewPoin.push_back(oPointBottom);
}
}
}
}
if (bFindBaby == false)
{
if (!vecNewPoin.empty())
{
mapFind[mapFind.size()] = vecNewPoin;
}
else
{
break;
}
}
}
unsigned int uiDistanse = mapFind.size() - 1;
unsigned int uiCost = uiDistanse * timePerRoad;
unsigned int uiCostMin(0);
for(size_t sCurSize = 0;sCurSize < vecResult.size();sCurSize++)
{
unsigned int uiWait = vecResult[sCurSize].PointWaitToRoot();
if (uiCostMin == 0)
{
uiCostMin = uiCost + uiWait;
cout << vecResult[sCurSize].PointOutputToRoot() << endl;
cout << "基准最短耗时:" << uiCostMin << endl;
}
else if (uiCostMin > uiCost + uiWait)
{
uiCostMin = uiCost + uiWait;
cout << vecResult[sCurSize].PointOutputToRoot() << endl;
cout << "发现更短耗时:" << uiCostMin << endl;
}
}
return uiCostMin;
}
int main()
{
int lights[10][10]={21,32,43,24,15,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,1,2,3,4,5,6,7,38,9,10,11,32,13,14,35,46,37,38,29,10,1,2,3,4,5,6,7,8,9,10,11,12,23,34,5,16,17,18,19,8,1,2,3,4,5,26,7,8,19,10,11,12,13,14,15,33,17,18,22,20,1,2,3,24,5,6,7,18,9,10,11,12,13,14,15,16,17,18,19,20};
CRoadPoint::SetPointMax(9,9);
int timePerRoad = 8;
int rowStart = 8;
int colStart = 7;
int rowEnd = 2;
int colEnd = 3;
int iRet = calcTime(lights, timePerRoad, rowStart, colStart, rowEnd, colEnd);
if (iRet > 0)
{
cout << "通过两个路口最短时间是:"<< iRet << endl;
}
return 0;
}