(干货菌:枚举和递归是所有算法的根基,所有算法也都是这两种思维的继续拓展。)
递归:某个函数直接或间接的调用自身。
f(x)=g(f(x-1)),已知f(0)的值和g(),就可以求出。
枚举是把一个问题划分为一组子问题(横向的),递归是把一个问题逐级分解成子问题(纵向的)。
解决:1、找出递归公式,2、找到递归终止条件。
小游戏:
游戏在一个分割成w*h个正方格子的矩形板上进行,每个正方格子上可以有一张游戏卡片,当然也可以没有。
问题描述(连连看):
当下面的情况满足时,认为两个游戏卡片之间有一条路径相连:
- 路径只包含水平或者竖直的直线段
- 路径不能穿过别的游戏卡片
- 但是允许路径临时的离开矩形板
输入:
- ·输入包括多组数据:一个矩形板对应一组数据
- ·第一行包括两个整数w和h(1<=w,h<=75),分别表示矩形板的宽度和长度
- ·下面的h行,每行包括W个字符,表示矩形板上的游戏卡片分布情况:
- ·使用X’表示这个地方有一个游戏卡片
- ·使用空格表示这个地方没有游戏卡片
- ·之后每行上包括4个整数:×1,y1,×2,y2(1<=x1,x2<=w,1<=y1,y2<=h)
- ·给出两个卡片在矩形板上的位置
- 注意:矩形板左上角的坐标是(1,1)输入保证这两个游戏卡片所处的位置是不相同的如果一行上有4个0,表示这组测试数据的结束
- ·如果一行上给出W=h=0,那么表示所有的输入结束了
输出:
- ·对每一个矩形板,输出一行“Board#n:",n是输入数据的编号
- ·对每一组需要测试的游戏卡片输出一行.这一行的开头是“Pairm:”,这里m是测试卡片的编号(对每个矩形板编号都从1开始)
- ·如果可以相连,找到连接这两个卡片的所有路径中包括线段数最少的路径,输出“k segments."
- k是找到的最优路径中包括的线段的数目
- ·如果不能相连,输出“impossible.”
- ·每组数据之后输出一个空行
迷宫求解问题:
- 自相似性表现在每走一步的探测方式相同,可以用递归方法求解
- 通过枚举方式找到从起点到终点的路径,朝一个方向走下去:
·如果走不通,则换个方向走
- >四个方向都走不通,则回到上一步的地方,换个方向走
- >依次走下去,直到走到终点
判断新位置(x,y)是否有效
·T1:(x,y)在边界之内
(x>-1)&&(x-1)&&(y
·T2:该位置没有游戏卡片并且未曾走过
((board[y][x]=="")&&(mark[y][x]==false))
·T3:已经到达终点
(x==end_x)&&(y==end_y)&&(board[y][x]=='X")
综上,(x,y)有效的条件是T1&&(T2||T3)
#include #include #define MAXIN 75char board[MAXIN+2J[MAXIN+2];/定义矩形板int minstep,w,h,to[4][2]={0,1},{1,0},{0-1},{-1,0};//定义方向bool mark[MAXIN+2][MAXIN+2];//定义标记数组void Search(int now_x,int now_y,int end_x,int end_y,int step,int f{ if(step>minstep)return;//当前路径数大于minstep,返回>优化策略 if(now_x==end_x&&now_y==end_y){ //到达终点 if(minstep>step)//更新最小路径数 minstep=step; return; } for(int i=0;i<4;i++){ //枚举下一步的方向 int x=now_x+to][0];/得到新的位置 int y=now_y+to[i][1]; if((x>-1)&&(x-1)&&(y0){ //读入起点和终点 count++;minstep=100000;//初始化minstep为一个很大的值 memset(mark,false,sizeof(mark)); //递归搜索 Search(begin_x,begin_y,end_x,end_y,0,-1); //输出结果 if(minstep<100000)printf("Pair%d:%d segments.In",count,minstep); else printf("Pair%d:impossible.",count); } printf(""); }return 0;}