Codevs1220 数字三角形
Codevs2193 数字三角形ww 和 Codevs2198 数字三角形www
Codevs2189 数字三角形w
最后找一遍那个目标状态存在即可了。
Vijos1006 晴天小猪历险记之Hill
最关键的是,要从左下角走到山顶……
由于由一个走过的点扩展而来的状态在决策时。是不可能再去选择这个点的。
这也就是说,左推仅仅能一直向左,右推仅仅能一直向右,也就是说。一个数的左右推值,仅仅会来自于它左右的两个数,显然左右推是不相互影响的。最后得到结果时。仅仅需将结果的四种来源取min,就能完毕任务。
当然,边界是须要特殊处理的。
个人认为。前三种不用给代码了,转移方程与思路都非常明白了……
于是,以下是Vijos1006的代码:
#include<stdio.h>
#define maxint 2000000000
#define min(a,b) (a<b?a:b)
long a[1000][1000]={0};
long d[1000][1000]={0};
int main()
{
long n,i,j,k,tmp,x1,x2;
scanf("%ld",&n);
for(i=0;i<n;i++)
for(j=0;j<=i;j++)
scanf("%ld",&a[i][j]);
for(i=0;i<n;i++)
for(j=0;j<=i;j++)
d[i][j]=maxint;
for(i=0;i<n;i++) //对最后一行的处理
d[n-1][i]=a[n-1][i];
for(i=1;i<n;i++)
d[n-1][i]=d[n-1][i-1]+a[n-1][i]; //由于最后一行右边的点仅仅能从左边的推来,所以有了这个预处理
for(i=n-1;i>=0;i--)
d[n-1][i]=min(d[n-1][i],d[n-1][(i+1)%n]+a[n-1][i]); //往左走的话。肯定要先从左边翻过去再向左走
for(i=n-2;i>=0;i--)
{
d[i][0]=min(d[i+1][0],d[i+1][1]); //对左边界的处理
d[i][0]=min(d[i][0],d[i+1][i+1]);
d[i][0]+=a[i][0];
d[i][i]=min(d[i+1][0],d[i+1][i]); //对右边界的处理
d[i][i]=min(d[i][i],d[i+1][i+1]);
d[i][i]+=a[i][i];
for(j=1;j<=i-1;j++) //对中间位置的处理。这时候以下的一行已经处理完了
d[i][j]=min(d[i+1][j],d[i+1][j+1])+a[i][j];
d[i][0]=min(d[i][0],d[i][i]+a[i][0]); //左推与右推
for(j=1;j<=i;j++)
d[i][j]=min(d[i][j],d[i][j-1]+a[i][j]);
for(j=i;j>=0;j--)
d[i][j]=min(d[i][j],d[i][(j+1)%(i+1)]+a[i][j]);
}
printf("%ld\n",d[0][0]);
return 0;
}
原文:http://www.cnblogs.com/mfmdaoyou/p/6939810.html