vijosP1006 晴天小猪历险记之Hill

时间:2022-12-30 04:22:42

vijosP1006 晴天小猪历险记之Hill

链接:https://vijos.org/p/1006

【思路】

图上DP。

这个题的递推顺序是关键。先从上一行得到最小值,然后从本行比较最小值,注意本行、本行与上一行之间的第一段与最后一段是相通的。

【代码】

 #include<cstdio>
#include<iostream>
#include<cstring>
#define FOR(a,b,c) for(int a=(b);a<=(c);a++)
using namespace std; const int maxn = +;
const int INF=<<; int w[maxn][maxn],d[maxn][maxn];
int n; int main()
{
scanf("%d",&n);
FOR(i,,n) FOR(j,,i) scanf("%d",&w[i][j]);
memset(d,,sizeof(d));
d[n][]=;
FOR(i,,n) d[n][i]=d[n][i-]+w[n][i];
for(int i=n-;i;i--)
{
FOR(j,,i) {
if(j==)
d[i][j]=min(d[i+][i+],min(d[i+][j],d[i+][j+]))+w[i][j];
else if(j==i) {
d[i][j]=min(d[i+][],min(d[i+][j],d[i+][j+]))+w[i][j];
}
else
d[i][j]=min(d[i+][j],d[i+][j+]) + w[i][j];
}
d[i][] = min(d[i][],d[i][i]+w[i][]);
FOR(j,,i) d[i][j] = min(d[i][j],d[i][j-] + w[i][j]);
for(int j=i-;j;j--) d[i][j] = min(d[i][j],d[i][j+] + w[i][j]);
}
printf("%d\n",d[][]);
return ;
}