TYVJ1106
巨坑。。。
和数字三角形原理差不多,就是状态多一点,而且前后状态有影响
坑1:在第i行,从第一个位置可以直接走到最后一个位置,说明没一层这是一个圆
坑2:第i行的第一个位置可以直接走到上面一行的最后一个位置,这尼玛还是一个圆锥啊。
设dp[i][j]表示到(i,j)时最小的分数,从下往上推
dp目标 dp[1][1]
(i,j)可以从左下、右下、左、右到达,从下往上还好说,这左右还可以走的话,不好办了。。
首先对于每一层,先由下面一层推上来,
一般情况dp[i][j]=a[i][j]+min(dp[i+1][j],dp[i+1][j+1])
特殊情况需特判(例如说山腰就是每一行开头和结尾的位置)
从下面推上来之后,遍历当前层,找到这一层的最小值,这个值可以确定就是dp[i][j]的值,然后再用这个点将这一层都更新一遍。从这个点向右推一圈(注意是一圈),向左推一圈,就可以把每个点都更新了,需要思考一下这个方法的正确性,但是不用怀疑,它确实是对的。
这破题从中午开始搞到下午三点,后来觉得没错了,交了几次,老是只有第七点,,后来拿了数据,怎么也过不了,当时那个烦呐,后来等到晚饭回来,看了一下,尼玛在一万个字母当中把几个i写成了n,改之,果断AC
1 //8594 4187 2 #include <cstdio> 3 #include <cstring> 4 #include <iostream> 5 #include <algorithm> 6 #define INF 11111111 7 using namespace std; 8 const int maxn = 1005; 9 int a[maxn][maxn],dp[maxn][maxn]; 10 int main() 11 { 12 //freopen("in.txt","r",stdin); 13 int n; 14 cin>>n; 15 memset(dp,0,sizeof(dp)); 16 memset(a,0,sizeof(a)); 17 for(int i = 1;i<=n;++i) 18 for(int j = 1;j<=i;++j) 19 scanf("%d",&a[i][j]); 20 for(int i = 0;i<=n+1;++i) 21 for(int j = 0;j<=n+1;++j) 22 dp[i][j] = INF; 23 dp[n][0] = 0; 24 for(int i = 1;i<=n;++i) 25 dp[n][i]=dp[n][i-1]+a[n][i]; 26 for(int i = n;i>=2;--i) 27 if(i==n)dp[n][i] = min(dp[n][i],dp[n][1]+a[n][i]); 28 else dp[n][i] = min(dp[n][i],dp[n][i+1]+a[n][i+1]); 29 for(int i = n-1;i>=1;--i) 30 { 31 //从下更新到上一层 32 for(int j = 1;j<=i;++j) 33 if(j==1)dp[i][j] = a[i][j]+min(dp[i+1][i+1],min(dp[i+1][j],dp[i+1][j+1])); 34 else if(j==i) dp[i][j]=a[i][j]+min(dp[i+1][1],min(dp[i+1][j],dp[i+1][j+1])); 35 else dp[i][j] = a[i][j]+min(dp[i+1][j],dp[i+1][j+1]); 36 //获取第i层最小dp的位置 37 int mmin = INF,min_x; 38 for(int j = 1;j<=i;++j)if(mmin>dp[i][j]){mmin = dp[i][j];min_x = j;} 39 //从最小位置向右更新一圈 40 for(int j = min_x+1;j<=i;++j)dp[i][j]=min(dp[i][j],dp[i][j-1]+a[i][j]); 41 dp[i][1] = min(dp[i][1],dp[i][i]+a[i][1]); 42 for(int j = 1;j<min_x;++j)dp[i][j] = min(dp[i][j],dp[i][j-1]+a[i][j]); 43 //从最小位置向左更新一圈 44 for(int j=min_x-1;j>=1;--j)dp[i][j]=min(dp[i][j],dp[i][j+1]+a[i][j]); 45 dp[i][i] = min(dp[i][i],dp[i][1]+a[i][i]); 46 for(int j=i;j>min_x;--j)dp[i][j]=min(dp[i][j],dp[i][j+1]+a[i][j]); 47 48 } 49 50 printf("%d\n",dp[1][1]); 51 return 0; 52 }
弱者究竟为何而战?!