每日总结:
1.迷宫问题
https://www.luogu.com.cn/problem/P1605
题目描述:
给定一个 N \times MN×M 方格的迷宫,迷宫里有 TT 处障碍,障碍处不可通过。
在迷宫中移动有上下左右四种方式,每次只能移动一个方格。数据保证起点上没有障碍。
给定起点坐标和终点坐标,每个方格最多经过一次,问有多少种从起点坐标到终点坐标的方案。
代码如下:
#include <stdio.h>
int mg[100][100];
int n,m,t,sx,sy,fx,fy;
int count;//可以到达终点的方案数
void dfs(int x,int y)
{
if(mg[x][y]==1)return;//走过或是障碍物
if(x<1||x>n||y<1||y>m)return;//处理边界问题
if(x==fx&&y==fy){
count++;
return;
}//坐标与终点坐标相同,到终点的方法数加一
mg[x][y]=1;//1用于表示障碍物或者是已经走过
dfs(x,y+1);//右
dfs(x+1,y);//下
dfs(x,y-1);//左
dfs(x-1,y);//上
mg[x][y]=0;//回溯,还原状态
}
void input()
{
int p,q;
scanf("%d%d%d",&n,&m,&t);
scanf("%d%d%d%d",&sx,&sy,&fx,&fy);
for(int i=0;i<t;i++)
{
scanf("%d%d",&p,&q);
mg[p][q]=1;//对障碍物所在的位置赋1
}
}//用于输入数据
int main(int argc, char *argv[])
{
input();
dfs(sx,sy);
printf("%d\n",count);
return 0;
}
首先全局数组内的值都为0,我们再将有障碍物的位置置1,然后从起点处开始向我们给定的方向顺序移动(我这里是右->下->左->上),但在这之前还要先判断当前位置是否能够到达(不超边界,没有障碍),当该位置能到时,就先置1,代表走过了,然后递归到可移动的位置,在不能动的情况下,回溯到上一个位置,然后换一个方向位移,直到抵达终点,方案数加一,然后回溯到上一个位置,看看有没有其他的方向可以走通,将各位置的所有方向全部探测完毕后,程序结束。
2.自然数拆分
https://www.luogu.com.cn/problem/P2404
题目描述:
任何一个大于 11 的自然数 nn,总可以拆分成若干个小于 nn 的自然数之和。现在给你一个自然数 nn,要求你求出 nn 的拆分成一些数字的和。每个拆分后的序列中的数字从小到大排序。然后你需要输出这些序列,其中字典序小的序列需要优先输出。
代码如下:
#include <stdio.h>
int m;//m用来记录n的值
int a[9]={1};
//第一个元素为一表示的是从1开始拆分
void print(int step)//step表示拆分了几个数
{
int i;
for(i=1;i<step;i++)printf("%d+",a[i]);
printf("%d\n",a[i]);
}
void dfs(int n,int step)
{
for(int i=a[step-1];i<=n;i++)//升序输出,后面的数不能小于前面
{
if(i<m)
{
a[step]=i;//记录拆分出来的数
n-=i;//n为剩下要拆分的数
if(n==0)print(step);//数已经拆分完,打印记录的数据
else dfs(n,step+1);
n+=i;//回溯后要还原状态
}
}
}
int main(int argc, char *argv[])
{
int n;
scanf("%d",&n);
m=n;
dfs(n,1);
return 0;
}
第一轮拆分后肯定将全是1,到了第二轮开始回溯,此时a从第二个元素开始为{1,1,1,1,1},n的值为2,因此将倒数第二个位置记录为2,n-2后为0,再次打印出来,然后又回溯,a{1,1,1,1},n的值为3,这里也是从2开始,但是将倒数第三的位置上记录了2后,n就只剩下了1,到了下一个位置后前一个数的值2比1要大,还是不行,然后回溯上去,将倒数第三的位置上记录上3,n-3后为0,将其打印出来,剩下的以此类推,最终完成所有拆分结果。