题目描述
在一个n*n的矩阵中,每个格子都有一个整数,PIPI位于矩阵的左上角,它想知道有多少条不同合法路线达到矩阵右下角。
行走规则如下:
(1)每次只能往下或往右走一步。
(2)格子中的整数表示从该点出发一步必须跨越的距离。
PS:对(1)和(2)条件的解释: 若此时在 (x,y) 并且格子上的数字为 k ,则下一步到达的位置为 (x+k,y)或 (x,y+k)
输入
多组数据
第一行为一个整数n,4<=n<=34.
接下来n行给出一个数字矩阵,0<=矩阵中元素<=9.
输出
对于每组数据输出一个整数,表示从左上角到右下角的不同路径数。
样例输入
4
2331
1213
1231
3110
4
3332
1213
1232
2120
5
11101
01111
11111
11101
11101
样例输出
3
0
7
本题用bfs会超内存,用递归会超时。。
先贴上递归
#include<iostream>
#include<cstring>
#include<string>
using namespace std;
int count=0,n;
int map[35][35];
int dp(int x, int y)
{
//cout<<"x="<<x<<"y="<<y<<map[x][y]<<endl;
if(x==n-1&&y==n-1)
{
count++;
return 0;
}
if(map[x][y]==0)
return 0;
if(x+map[x][y]<n)
{
dp(x+map[x][y],y);
}
if(y+map[x][y]<n)
{
// cout<<"hi";
dp(x,y+map[x][y]);
}
}
int main()
{
string ma[35];
while(cin>>n)
{
int i,j;
for(i=0;i<n;i++)
cin>>ma[i];
for(i=0;i<n;i++)
for(j=0;j<n;j++)
map[i][j]=(int)(ma[i][j]-'0');
count=0;
i=dp(0,0);
cout<<count<<endl;
}
return 0;
}
然后是正确写法:dp
动态规划思想:每一个点都由它上面点的和左边的点到达。因此遍历其上面的和左边的点。用dp[i][j]记录从起点到(i,j)有多少条路径。
初始将起点的dp设置为1,其他点的dp都置0,这样就可以确保只有来自起点的点才能被记录。
#include<iostream>
#include<cstring>
#include<string>
using namespace std;
int main()
{
int n;
string ma[35];
int map[35][35];
while(cin>>n)
{
int i,j,k;
long long dp[35][35];//dp[i][j]起点到(i,j)的路径数
memset(dp,0,sizeof(dp));
for(i=0;i<n;i++)
cin>>ma[i];
for(i=0;i<n;i++)
for(j=0;j<n;j++)
map[i][j]=(int)(ma[i][j]-'0');
dp[0][0]=1; //起点为1
for(i=0;i<n;i++)
for(j=0;j<n;j++)
{
for(k=0;k<j;k++)//先遍历从左边来的节点
{
if(map[i][k]+k==j)
dp[i][j]+=dp[i][k];//只有是来自起点的点才是不会加0
}
for(k=0;k<i;k++)//遍历从上边来的节点
{
if(map[k][j]+k==i)
dp[i][j]+=dp[k][j];
}
}
cout<<dp[n-1][n-1]<<endl;
}
return 0;
}