#I. 数字三角形1
Description
给出一个数字三角形,你从[1,1]开始出发,走到最后一行。每次站在一个点上时,可以向下走,或者向右下走。将经过的数字加起来,希望其和最大。
7
3 8
8 1 0
2 7 4 4
4 5 2 6 5
Format
Input
第一行给出数字N
接下来N行描述这个数字三角形,所给出的数字为100以内的正整数。
N<=100
Output
如题
Samples
输入数据 1
5
7
3 8
8 1 0
2 7 4 4
4 5 2 6 5
输出数据 1
30
递归
可加记忆化优化
#include<bits/stdc++.h>
using namespace std;
int n,v[110][110],ex[110][110];//记忆化,ex[i][j]代表从(1,1)走到(i,j)的最大代价
int ans;
int walk(int x,int y)
{
if(x==1&&y==1)//出口:已知(1,1)到(1,1)的代价
return v[1][1];
if(ex[x][y]==0)
if(y==1)//注意过界
ex[x][y]=v[x][y]+walk(x-1,y);
else
if(x==y)//注意过界
ex[x][y]=v[x][y]+walk(x-1,y-1);
else
ex[x][y]=v[x][y]+max(walk(x-1,y-1),walk(x-1,y));
return ex[x][y];
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
for(int j=1;j<=i;j++)
scanf("%d",&v[i][j]);//代价
for(int i=1;i<=n;i++)
walk(n,i);
for(int i=1;i<=n;i++)
ans=max(ans,ex[n][i]);//最大代价
printf("%d",ans);
return 0;
}
[点击并拖拽以移动]
#include<bits/stdc++.h>
using namespace std;
int n,v[110][110],ex[110][110];//记忆化,ex[i][j]代表从(i,j)走到第n行的最大代价
int walk(int x,int y)
{
if(x==n)
return v[x][y];//出口:从第n行到第n行代价已知
if(ex[x][y]==0)
ex[x][y]=v[x][y]+max(walk(x+1,y),walk(x+1,y+1));
return ex[x][y];
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
for(int j=1;j<=i;j++)
scanf("%d",&v[i][j]);//代价
printf("%d",walk(1,1));
return 0;
}
#J. 马的遍历
Description
中国象棋大家都玩过吧!!!
现在有只小马迷路了,它现在在左下角的(0,0)位置,它的家在右上角的(m,n)位置
(棋盘大小为m*n)
现规定小马只能往右走,请聪明的你帮帮小马算一下回到家有几种方案?
注意:
(0,0)点在左下角,(m,n)在右上角,
棋盘内所有点的坐标(x,y)
满足x>=0&&x<=m&&y>=0&&y<=n
Format
Input
家的位置m,n
1=<m,n<=30
Output
一个整数即方案数
Samples
【输入样例】
输入数据 1
4 8
输出数据 1
37
递归+记忆化
注意:涉及有边界的位移,调用数组前要判断是否出界
#include<bits/stdc++.h>
using namespace std;
int n,m,v[34][34];
int missin(int x,int y)
{
if(x==m&&y==n)
{
v[x][y]=1;
return 1;
}
if(x<0||y<0||x>m||y>n)
return 0;
if(v[x][y])
return v[x][y];
v[x][y]=missin(x+1,y+2)+missin(x-1,y+2)+missin(x+2,y+1)+missin(x-2,y+1);
return v[x][y];
}
int main()
{
memset(v,0,sizeof(v));
scanf("%d %d",&m,&n);
printf("%d",missin(0,0));
return 0;
}