在一个4X4方格线上,1只蚂蚁从A点出发,沿着方格线爬到B点简析

题目

在一个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,14,24,34,4
3,13,23,33,4
2,12,22,32,4
1,11,21,31,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
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值