背景
在很久很久以前,有一个动物村庄,那里是猪的乐园(^_^),村民们勤劳、勇敢、善良、团结……
不过有一天,最小的小小猪生病了,而这种病是极其罕见的,因此大家都没有储存这种药物。所以晴天小猪自告奋勇,要去采取这种药草。于是,晴天小猪的传奇故事便由此展开……
描述
这一天,他来到了一座深山的山脚下,因为只有这座深山中的一位隐者才知道这种药草的所在。但是上山的路错综复杂,由于小小猪的病情,晴天小猪想找一条需时最少的路到达山顶,但现在它一头雾水,所以向你求助。
山用一个三角形表示,从山顶依次向下有1段、2段、3段等山路,每一段用一个数字T(1<=T<=100)表示,代表晴天小猪在这一段山路上需要爬的时间,每一次它都可以朝左、右、左上、右上四个方向走。山是环形的。(**注意**:在任意一层的第一段也可以走到本层的最后一段或上一层的最后一段)。
晴天小猪从山的左下角出发,目的地为山顶,即隐者的小屋。
★★★**本题为vijos早年陈题,描述晦涩,现重新描述题面如下**★★★
有一个数字三角形,共nn行,依次编号为第一行,第二行至第nn行。其中第ii行有ii个数字,位置依次记为(i,1),(i,2)(i,1),(i,2)到(i,i)(i,i)。
现在从第nn层的第一个位置出发(即(n,1)(n,1)),每一步移到相邻的,且行编号小于或等于当前行编号的一个位置中,直到(1,1)(1,1)结束,在不重复经过任何位置的情形下,路过的所有位置(包括端点)的对应数字之和最小。
下面详细定义相邻关系。
同一层内连续的两个位置相邻,特别的有每一层第一个位置与最后一个位置相邻。
对于位置(i,j)(i,j),它与(i-1,j-1)(i−1,j−1)以及(i-1,j)(i−1,j)相邻,特别的(i,1)(i,1)与(i-1,i-1)(i−1,i−1)相邻,且(i,i)(i,i)与(i-1,1)(i−1,1)相邻。
格式
输入格式
第一行有一个数n(2<=n<=1000),表示山的高度。
从第二行至第n+1行,第i+1行有i个数,每个数表示晴天小猪在这一段山路上需要爬的时间。
输出格式
一个数,即晴天小猪所需要的最短时间。
样例1
样例输入1
5
1
2 3
4 5 6
10 1 7 8
1 1 4 5 6
样例输出1
10
限制
各个测试点1s
提示
在山的两侧的走法略有特殊,请自己模拟一下,开始我自己都弄错了……
来源
Sunnypig
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <iostream> 2 #include <cstdio> 3 #include <memory.h> 4 #include <algorithm> 5 6 using namespace std; 7 int mou[1001][1001]={0},f[1001][1001]={0}; 8 9 int main() 10 { 11 int n; 12 scanf("%d",&n); 13 for(int i=1;i<=n;i++) 14 for(int j=0;j<i;j++) 15 scanf("%d",&mou[i][j]); 16 f[1][0]=mou[1][0]; 17 //先从上往下走算出最小值 18 for(int x=2;x<=n;x++) 19 { 20 for(int y=0;y<x;y++) 21 f[x][y]=min(f[x-1][(y-2+x)%(x-1)],f[x-1][y%(x-1)])+mou[x][y]; 22 //再分别从左和右推一遍最小值 23 for(int y=0;y<x;y++) 24 f[x][y]=min(f[x][y],f[x][(y-1+x)%x]+mou[x][y]); 25 for(int y=x-1;y>=0;y--) 26 f[x][y]=min(f[x][y],f[x][(y+1)%x]+mou[x][y]); 27 //二遍推(感觉应该需要但好像不要也能过??不懂为啥) 28 for(int y=0;y<x;y++) 29 f[x][y]=min(f[x][y],f[x][(y-1+x)%x]+mou[x][y]); 30 for(int y=x-1;y>=0;y--) 31 f[x][y]=min(f[x][y],f[x][(y+1)%x]+mou[x][y]); 32 } 33 printf("%d ",f[n][0]); 34 return 0; 35 }
一开始搞错了顺序 从下往上推了T^T然而那样的话就完全不对了……
所以导致数组顺序安排改来改去的最后设成了从0开始存数字非常不方便
最后总算是debug对了
未解决的问题:由于一开始是由下往上推所以算了从起点到最后一行所有数所用的最小时间,后来改为由上而下之后就没把这个去掉直接用了 按理来说在最后一行也只有往左走往右走一条路 只要加上这两条路中较小的时间花费就可以了 为什么wa了一部分数据呢??
错误代码:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <iostream> 2 #include <cstdio> 3 #include <memory.h> 4 #include <algorithm> 5 6 using namespace std; 7 int mou[1001][1001]={0},f[1001][1001]={0}; 8 9 int main() 10 { 11 int n; 12 scanf("%d",&n); 13 for(int i=1;i<=n;i++) 14 for(int j=0;j<i;j++) 15 scanf("%d",&mou[i][j]); 16 f[1][0]=mou[1][0]; 17 //第n行的情况 18 f[n][0]=mou[n][0]; 19 for(int y=1;y<n;y++) 20 { 21 int r=mou[n][0],l=mou[n][0]; 22 for(int i=1;i<=y;i++) 23 r+=mou[n][i]; 24 for(int i=n-1;i>=y;i--) 25 l+=mou[n][i]; 26 f[n][y]=r<l?r:l; 27 } 28 //其他行的情况 29 //先从上往下走算出最小值 30 for(int x=2;x<=n-1;x++) 31 { 32 for(int y=0;y<x;y++) 33 f[x][y]=min(f[x-1][(y-2+x)%(x-1)],f[x-1][y%(x-1)])+mou[x][y]; 34 //再分别从左和右推一遍最小值 35 for(int y=0;y<x;y++) 36 f[x][y]=min(f[x][y],f[x][(y-1+x)%x]+mou[x][y]); 37 for(int y=x-1;y>=0;y--) 38 f[x][y]=min(f[x][y],f[x][(y+1)%x]+mou[x][y]); 39 //二遍推(感觉应该需要但好像不要也能过??不懂为啥) 40 for(int y=0;y<x;y++) 41 f[x][y]=min(f[x][y],f[x][(y-1+x)%x]+mou[x][y]); 42 for(int y=x-1;y>=0;y--) 43 f[x][y]=min(f[x][y],f[x][(y+1)%x]+mou[x][y]); 44 } 45 int min0=999999; 46 for(int y=0;y<n;y++) 47 { 48 f[n][y]=min(f[n-1][(y-1+n)%(n-1)],f[n-1][y%(n-1)])+f[n][y]; 49 if(y==0) 50 min0=f[n][y]; 51 if(min0>f[n][y]) 52 min0=f[n][y]; 53 } 54 printf("%d ",min0); 55 return 0; 56 }