题目
在一个4*4方格线上,1只蚂蚁从A点出发,沿着方格线爬到B点,如下图所示,规定每次只能向右或向上爬,问:
1. 从A到B有多少条不同的路线?
一共8步,从中选出向右走的4步,剩下4步向上走。即8选4, C48 =70
2. 如果把方格线扩展为n*m,则又有多少条不同的路线?
Cnn+m 原理同上。
3. 突然天降暴雨,洪水冲断了s条线段
假如蚂蚁可以朝任意方向爬了,被洪水冲断的线段是随机位置的,请写出程序代码
输入:一串下列结构的链表,每个节点表示x1y1到x2y2的路线是被洪水冲断的
typedef struct broken_road_s
{
struct broken_road_s *next;
int x1;
int y1;
int x2;
int y2;
}broken_road_t;
输出为蚂蚁从起点到终点的路径链表,如果不可达输出为0(请自己设计输出的结构体)
4,1 | 4,2 | 4,3 | 4,4 |
---|---|---|---|
3,1 | 3,2 | 3,3 | 3,4 |
2,1 | 2,2 | 2,3 | 2,4 |
1,1 | 1,2 | 1,3 | 1,4 |
从左下角走到右上角
路径规划分析
1、首先将问题建模
位置建模:坐标(x,y)。从左下角到右上角,也即从0,0点到4,4点。
地图建模:二维数组。任何一个位置均有4个方向,上下左右,用1表示可以走得通,用0表示走不通,用bit0 bit1表示左方向(预留一位备用,比如如果要表示初始状态,状态已经被确定状态等),bit1 bit2表示下方向,依次类推。则可以用一个二维数组表示出路径通断的情况。
参数设定简析:相邻的两个点的值有对称关系。即下方的点向上走不通则上方的点向下也走不通。左右方向同理。
从一点走到另一点算法简析:采用递归。一次只走一步,即从当前点走到相邻的点。若相邻点可行,则按一定的偏好走向下一点(偏好即方向优先顺序,比如右、上、左下),若可到达终点,将当前位置放入队列。若相邻方向均不通,则回退到前一点,尝试剩余几个方向,直到有一个方向走下去可以到达终点。
2、代码如下
头文件
#ifndef PUZZLE_H
#define PUZZLE_H
#include <vector>
#include <stack>
#include <string>
#include <math.h>
#include <iostream>
class Puzzle
{
public:
Puzzle(int row,int col);
virtual ~Puzzle(){};
std::vector<std::vector<int> > road;
int paveOneWay();
std::vector<std::string> onePath;
//设置某个位置某几个方向的通断情况,同时设置相邻位置对应方向的值
int setPosDirVal(int row,int col,std::vector<int> dir,std::vector<int> val);
enum {step=2,
left=1,
down=left<<step,
right=down<<step,
up=right<<step};
private:
int setPosDirVal(int row,int col,int dir,int val, int update);
int goToNext(int curRow, int col, int lastRow, int lastCol);
int rowNum_;
int colNum_;
int runTimes_;
};
#endif // PUZZLE_H
源文件
#include "puzzle.h"
Puzzle::Puzzle(int row, int col):rowNum_(row),colNum_(col)
{
std::vector<int> v;
v.assign(col,0);
road.assign(row,v);
}
int Puzzle::paveOneWay()
{
runTimes_=0;
onePath.clear();
goToNext(0,0,0,0);
}
int Puzzle::setPosDirVal(int row, int col, std::vector<int> dir, std::vector<int> val)
{
int nRet=0;
for(int i=0;i<dir.size();i++){
nRet+=setPosDirVal(row,col,dir.at(i),val.at(i),1);
}
return nRet;
}
int Puzzle::setPosDirVal(int row, int col, int dir, int val, int update)
{
if(row<0 | col<0 | row>rowNum_-1 | col>colNum_-1)
return -1;
std::cout<<" row col dir val "<<row<<" "<<col<<" "<<dir<<" "<<val<<std::endl;
int nRet=1;
//首行下空,尾行上空
if(row==0){
road.at(row).at(col)=(road.at(row).at(col) | (down<<1)) & (~down);
}else if(row == rowNum_-1){
road.at(row).at(col)=(road.at(row).at(col) | (up<<1)) & (~up);
}
//首列左空,尾列右空
if(col==0){
road.at(row).at(col)=(road.at(row).at(col) | (left<<1)) & (~left);
}else if(col == colNum_-1){
road.at(row).at(col)=(road.at(row).at(col) | (right<<1)) & (~right);
}
//设置当前位置值
road.at(row).at(col)=(road.at(row).at(col) | (dir<<1)) & (~ (dir*(1-val%2)));
//设置相邻位置对称方向上的值
if(update){
switch(dir){
case left:
col--;
break;
case down:
row--;
break;
case right:
col++;
break;
case up:
row++;
break;
default:
break;
}
dir = pow((double)2,(double)(((int)(2+log(dir)))%4));
nRet+=setPosDirVal(row,col,dir,val,0);
}
return nRet;
}
int Puzzle::goToNext(int row, int col, int lastRow, int lastCol)
{
runTimes_++;
if(col == colNum_-1 && row == rowNum_-1)
return 1;
//优先顺序,右,上,左下。
if(road.at(row).at(col) & right){ //向右可行
if(col+1<colNum_){ //向右未越界
if(goToNext(row,col+1,row,col)){ //向右递归到达了目的地
onePath.push_back("right");
return 1;
}
}
}
if(road.at(row).at(col) & up){ //向上可行
if(row+1<rowNum_){ //向上未越界
if(goToNext(row+1,col,row,col)){ //向上递归到达了目的地
onePath.push_back("up");
return 1;
}
}
}
if(road.at(row).at(col) & left){ //向左可行
if((col-1>-1) && (col-1!=lastCol)){ //向左未越界且不是回到前一位置
if(goToNext(row,col-1,row,col)){ //向左递归到达了目的地
onePath.push_back("left");
return 1;
}
}
}
if(road.at(row).at(col) & down){ //向下可行
if((row-1>-1) && (row-1!=lastRow)){ //向下未越界且不是回到前一位置
if(goToNext(row-1,col,row,col)){ //向下递归到达了目的地
onePath.push_back("down");
return 1;
}
}
}
}
测试代码:
int row=4;
int col=4;
Puzzle puz(row,col);
std::vector<int> v;
v.assign(col,0xff);
puz.road.assign(row,v);
puz.setPosDirVal(0,0,
std::vector<int>({puz.right}),
std::vector<int>({0}));
puz.setPosDirVal(1,2,
std::vector<int>({puz.right}),
std::vector<int>({0}));
std::cout<<puz.paveOneWay()<<std::endl;
std::bitset<8> bit;
for(int i=puz.road.size()-1;i>-1;i--){
for(int j=0;j<puz.road.at(i).size();j++){
bit=puz.road.at(i).at(j);
std::cout<<std::hex<<puz.road.at(i).at(j)<<"("<<bit.to_string().c_str()<<")"<<" ";
}
std::cout<<std::endl;
}
for(int i = puz.onePath.size()-1;i>-1;i--){
std::cout<<puz.onePath.at(i).c_str()<<std::endl;
}
输出如下:
row col dir val 0 0 16 0
row col dir val 0 1 1 0
row col dir val 1 2 16 0
row col dir val 1 3 1 0
1
ff(11111111) ff(11111111) ff(11111111) ff(11111111)
ff(11111111) ff(11111111) ff(11111111) ff(11111111)
ff(11111111) ff(11111111) ef(11101111) ee(11101110)
ea(11101010) fa(11111010) ff(11111111) ff(11111111)
up
right
right
up
right
up