自然数的拆分问题
题目描述
任何一个大于 $1$ 的自然数 $n$,总可以拆分成若干个小于 $n$ 的自然数之和。现在给你一个自然数 $n$,要求你求出 $n$ 的拆分成一些数字的和。每个拆分后的序列中的数字从小到大排序。然后你需要输出这些序列,其中字典序小的序列需要优先输出。
输入格式
输入:待拆分的自然数 n。
输出格式
输出:若干数的加法式子。
样例 1
样例输入
7
样例输出 #1
1+1+1+1+1+1+1
1+1+1+1+1+2
1+1+1+1+3
1+1+1+2+2
1+1+1+4
1+1+2+3
1+1+5
1+2+2+2
1+2+4
1+3+3
1+6
2+2+3
2+5
3+4
```
提示
数据保证 1<=n<=8。
思路:这个题使用DPS就可以解决,假设我们输入7,数组内有 1 1 1 1 1 1 1 ,然后最后一个1变为2,从2~6去试,看看此时的sum等不等于7,要是为7,我们就打印数组得到结果,要是不都等于7(也就是大于),就回到 1 1 1 1 1 1 (6),也就是6个1的状态,再让最后一个1从2~6去试,要是sum都不等于7,就回到 1 1 1 1 1(6) (6),也就是5个1的状态,依次递归,来得到不同结果下的答案
#include<bits/stdc++.h>
using namespace std;
int arr[200],n;
void print(int cnt)
{
printf("%d",arr[0]);
for(int i=1;i<cnt;i++)
printf("+%d",arr[i]);
printf("\n");
}
void dps(int pos,int cnt,int sum)
{
if(sum>n)
return ;
else if(sum==n)
{
print(cnt);
}
else
{
for(int i=pos;i<n;i++)
{
arr[cnt]=i;
dps(i,cnt+1,sum+i);
}
}
}
int main()
{
scanf("%d",&n);
dps(1,0,0);
return 0;
}
题目描述
给定一个 N×M 方格的迷宫,迷宫里有 T 处障碍,障碍处不可通过。
在迷宫中移动有上下左右四种方式,每次只能移动一个方格。数据保证起点上没有障碍
给定起点坐标和终点坐标,每个方格最多经过一次,问有多少种从起点坐标到终点坐标的方案
输入格式
第一行为三个正整数 N,M,TN,M,T,分别表示迷宫的长宽和障碍总数
第二行为四个正整数 SX,SY,FX,FY SX,SY 代表起点坐标,FX,FY 代表终点坐标。
接下来 T 行,每行两个正整数,表示障碍点的坐标。
输出格式
输出从起点坐标到终点坐标的方案总数
输入输出样
输入
2 2 1
1 1 2 2
1 2
输出
1
思路:也是一样的用DPS就可以解决,我们先将迷宫中可以走的赋值为1,不可以(或走过的)走的赋值为0,首先将起点坐标给传入dps,然后对坐标的上下左右四个发现进行判断,如果周围不为0,我们先将这个坐标设为0(因为走过了),然后将这个坐标递归传入dps中,再进行判断,但是要注意:如果不满足递归条件后跳出的坐标,我们要重新赋值为1(相当于没走这个坐标),然后判断它的周围的其他坐标,然后如果遇到了结束坐标,我们就++,最后得到答案
#include<bits/stdc++.h>
using namespace std;
int arr[15][15]={0},n,m,ans=0,t,x,y,sx,sy,fx,fy;
int dx[4]={-1,1,0,0},dy[4]={0,0,-1,1};
void dfs(int x,int y)
{
if(x==fx&&y==fy)
{
ans++;
return ;
}
else
{
for(int i=0;i<4;i++)
{
if(arr[x+dx[i]][y+dy[i]]!=0)
{
arr[x+dx[i]][y+dy[i]]=0;
dfs(x+dx[i],y+dy[i]);
arr[x+dx[i]][y+dy[i]]=1;
}
}
}
}
int main()
{
cin>>n>>m>>t;
cin>>sx>>sy>>fx>>fy;
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
arr[i][j]=1;
arr[sx][sy]=0;
for(int i=0;i<t;i++)
{
cin>>x>>y;
arr[x][y]=0;
}
dfs(sx,sy);
cout<<ans;
return 0;
}