题目描述
这一天,他来到了一座深山的山脚下,因为只有这座深山中的一位隐者才知道这种药草的所在。但是上山的路错综复杂,由于小小猪的病情,晴天小猪想找一条需时最少的路到达山顶,但现在它一头雾水,所以向你求助。
山用一个三角形表示,从山顶依次向下有1段、2段、3段等山路,每一段用一个数字T(1< =T< =100)表示,代表晴天小猪在这一段山路上需要爬的时间,每一次它都可以朝左、右、左上、右上四个方向走(注意:在任意一层的第一段也可以走到本层的最后一段或上一层的最后一段)。
晴天小猪从山的左下角出发,目的地为山顶,即隐者的小屋。输入数据
第一行有一个数 n (2≤n≤1000),n (2≤n≤1000), 表示山的高度。
从第二行至第 n+1n+1 行,第 i+1i+1 行有 ii 个数,每个数表示晴天小猪在这一段山路上需要爬的时间。输出数据
一个数,即晴天小猪所需要的最短时间。
样例输入
5 1 2 3 4 5 6 10 1 7 8 1 1 4 5 6
样例输出
10
样例说明
在山的两侧的走法略有特殊,请自己模拟一下,开始我自己都弄错了……
解析:类似金字塔,但是,同一层内左右可以移动,第一段可以到达最后一段,即环形;上下层之间, 本层的第一段可以到达上一层的最后一段!!!
采取方式:先根据求解金字塔的方式求出dp[i][j],然后,在同一层里尝试左右走。因为是一个环形,所以采用走两遍的方式!!!(个人理解,是为了满足,任意段都有两种方式到达同层的另一段)
完整代码:
#include<iostream> #include<cmath> #define MAXN 1010 #define INF 2000000010 using namespace std; int road[MAXN][MAXN]; int dp[MAXN][MAXN]; int main() { int n; cin>>n; int i,j; for(i=1;i<=n;++i) for(j=1;j<=i;++j) cin>>road[i][j]; dp[n][1]=road[n][1]; //起点 for(i=2;i<=n;++i) dp[n][i]=INF; for(i=2;i<=n;++i) //向右走 dp[n][i]=min(dp[n][i],dp[n][i-1]+road[n][i]); dp[n][n]=min(dp[n][n],dp[n][1]+road[n][n]); //最后一个点可以由第一个点直接达到(环形) for(i=n-1;i>=1;--i)//向左走 dp[n][i]=min(dp[n][i],dp[n][i+1]+road[n][i]); for(i=n-1;i>=1;--i) //从下往上走 { for(j=1;j<=i;++j)//金字塔 dp[i][j]=min(dp[i+1][j],dp[i+1][j+1])+road[i][j]; dp[i][i]=min(dp[i][i],dp[i+1][1]+road[i][i]); //右端 顶点 可由下一层的左端顶点过来 dp[i][1]=min(dp[i][1],dp[i+1][i+1]+road[i][1]); //左端 顶点 由下一层的右端顶点过来 for(j=2;j<=i;++j)//向右走 dp[i][j]=min(dp[i][j],dp[i][j-1]+road[i][j]); dp[i][1]=min(dp[i][1],dp[i][i]+road[i][1]); for(j=i-1;j>=1;--j)//向左走 dp[i][j]=min(dp[i][j],dp[i][j+1]+road[i][j]); dp[i][i]=min(dp[i][i],dp[i][1]+road[i][i]); for(j=2;j<=i;++j)//向右走 dp[i][j]=min(dp[i][j],dp[i][j-1]+road[i][j]); dp[i][1]=min(dp[i][1],dp[i][i]+road[i][1]); for(j=i-1;j>=1;--j)//向左走 dp[i][j]=min(dp[i][j],dp[i][j+1]+road[i][j]); dp[i][i]=min(dp[i][i],dp[i][1]+road[i][i]); } cout<<dp[1][1])<<endl; }
参考资料:https://blog.csdn.net/qq_35479641/article/details/52523761