solve
- 要跑两遍dp
- 要不然从左右端点转移不过来
- 注意左下的转移是从j而不是从j+1(可以理解为金字塔但不是金字塔,而是样例给的样子)
Code
#include<bits/stdc++.h>
using namespace std;
const int maxn=1010;
int dp[maxn][maxn];
int g[maxn][maxn];
int n;
int mymin(int a,int b,int c,int d)
{
a=min(a,b);
a=min(a,c);
a=min(a,d);
return a;
}
int myminn(int a,int b,int c,int d,int e)
{
a=min(a,b);
a=min(a,c);
a=min(a,d);
a=min(a,e);
return a;
}
int main()
{
cin >> n;
memset(dp,0x3f,sizeof(dp));
for (int i=1;i<=n;i++)
{
for (int j=1;j<=i;j++)
{
cin >> g[i][j];
}
}
dp[n][1]=g[n][1];
for (int i=n;i>=1;i--)
{
dp[i][1]=min(dp[i][1],dp[i][i]+g[i][1]);
dp[i][1]=min(dp[i][1],dp[i+1][i+1]+g[i][1]);
// 对于每行头的转移
for (int j=1;j<=i;j++)
{
dp[i][j]=min(dp[i][j],dp[i][j-1]+g[i][j]);
dp[i][j]=min(dp[i][j],min(dp[i+1][j],dp[i+1][j+1])+g[i][j]);
}
dp[i][i]=min(dp[i][i],dp[i][1]+g[i][i]);
dp[i][i]=min(dp[i][i],dp[i+1][1]+g[i][i]);
// 对于每行尾的转移
for (int j=i-1;j>=1;j--)
{
dp[i][j]=min(dp[i][j],dp[i][j+1]+g[i][j]);
}
// 第二次
dp[i][1]=min(dp[i][1],dp[i][i]+g[i][1]);
dp[i][1]=min(dp[i][1],dp[i+1][i+1]+g[i][1]);
for (int j=1;j<=i;j++)
{
dp[i][j]=min(dp[i][j],dp[i][j-1]+g[i][j]);
dp[i][j]=min(dp[i][j],min(dp[i+1][j],dp[i+1][j+1])+g[i][j]);
}
dp[i][i]=min(dp[i][i],dp[i][1]+g[i][i]);
dp[i][i]=min(dp[i][i],dp[i+1][1]+g[i][i]);
}
cout << dp[1][1] << endl;
return 0;
}