以上是acwing的题谱
大致的题意就是给出一个n行的序列,序列的第i行有i个元素(i=1,2,3,...,n),需要你求出沿着这个序列从顶端走到底端元素和最大的一条路线
给三角形的每一行每一列标上号,以当前位于第i行第j列来表示状态,用来的方向进行状态转移。
dp思路如下:
https://www.acwing.com/problem/content/1017/
有点类似于bfs走迷宫的问题,思路和朴素版差不多。这里更复杂的是可能会出现不同的情况,比如说某些格子不能走、不能重复走这些问题。
#include
using namespace std;
const int N=110;
int T;
int dx[2]={-1,0},dy[2]={0,-1};
int m[N][N];
int f[N][N];
int main()
{
scanf("%d",&T);
while(T--)
{
int r,c;
scanf("%d%d",&r,&c);
for(int i=0;i<=r+1;i++)
for(int j=0;j<=c+1;j++) f[i][j]=0;
for(int i=1;i<=r;i++)
for(int j=1;j<=c;j++)
{
scanf("%d",&m[i][j]);
}
for(int i=1;i<=r;i++)
for(int j=1;j<=c;j++)
{
for(int k=0;k<2;k++)
{
int cx=i+dx[k],cy=j+dy[k];
f[i][j]=max(f[cx][cy]+m[i][j],f[i][j]);
}
}
printf("%d\n",f[r][c]);
}
}
登录—专业IT笔试面试备考平台_牛客网
设有N*N的方格图(N ≤ 10,我们将其中的某些方格中填入正整数,而其他的方格中则放入数字0。如下图所示(见样例):
某人从图的左上角的A 点出发,可以向下行走,也可以向右走,直到到达右下角的B点。在走过的路上,他可以取走方格中的数(取走后的方格中将变为数字0)。
此人从A点到B 点共走两次,试找出2条这样的路径,使得取得的数之和为最大。
这里需要考虑两条路线的情况,我们的状态就变成了[i1][j1]和[i2][j2]这样一个四维的状态。
四维的状态还可以继续优化,我们分析可以发现,因为每当一个点被路过时,上面的东西就会被拿走,所以两个人先后走还是同时走时没有差别的。我们考虑同时走的情况,就存在有i1+j1=i2+j2这个性质,因此我们使k=i1+j1=i2+j2,用[k][i1][i2]这个三维的状态可以代替原来四维的状态。
每走一步我们需要判断当前1和2是否处于一个格子,避免出现同一件物品拿两次的情况。
#include
using namespace std;
const int N=15;
int f[N*2][N][N];
int g[N][N];
int main()
{
int n;
scanf("%d",&n);
int a,b,c;
while(cin>>a>>b>>c,a||b||c) g[a][b]=c;
for(int k=2;k<=2*n;k++)
for(int i1=1;i1<=n;i1++)
for(int i2=1;i2<=n;i2++)
{
int j1=k-i1,j2=k-i2;
if(j1>0&&j1<=n&&j2>0&&j2<=n)
{
int w;
if(i1==i2) w=g[i1][j1];
else w=g[i1][j1]+g[i2][j2];
f[k][i1][i2]=max(f[k-1][i1][i2]+w,f[k][i1][i2]);
f[k][i1][i2]=max(f[k-1][i1-1][i2-1]+w,f[k][i1][i2]);
f[k][i1][i2]=max(f[k][i1][i2],f[k-1][i1][i2-1]+w);
f[k][i1][i2]=max(f[k][i1][i2],f[k-1][i1-1][i2]+w);
}
}
printf("%d",f[2*n][n][n]);
}
题解可以参见之前写的这篇文章:DP-线性DP的一些题目-CSDN博客