poj2353Ministry<DP>
链接:http://poj.org/problem?id=2353
题意:
给定一矩阵,求从第一层走到最后一层,的最小花费, 每次只能走到相邻的位置,,输出最小花费路径;
思路:
看完题想到 DP 方程为 dp[i][j] = min( dp[i][j-1], dp[i][j+1], dp[i-1][j] )+cost[i][j];
可是 dp[i][j] 与 dp[i][j-1]和dp[i][j+1]有关感觉不靠谱,可是又没想到别的有效的办法;
后来又看了下发现到达某一层后每次只会选择一个方向, 要么左要么右, 于是我们就可以做两次比较;
dp[i][j] = min( dp[i][j-1], dp[i-1][j] )+cost[i][j];
dp[i][j] = min( dp[i][j+1], dp[i-1][j] )+cost[i][j];
大家都称之为双向DP,姑且就这么叫吧;
坑爹的还有要记录路径,
View Code
1 #include<stdio.h> 2 #include<string.h> 3 #include<stdlib.h> 4 int dp[110][510]; 5 int cost[110][510], way[110][510], n, m; 6 void Print( int r, int c ) 7 { 8 if( r == 0 ){ 9 printf("%d\n", c+1); 10 return; 11 } 12 int x = way[r][c]/m, y = way[r][c]%m; 13 Print(x, y); 14 printf("%d\n", c+1); 15 16 } 17 int main() 18 { 19 while( scanf("%d%d", &n,&m) != EOF){ 20 for(int i = 0; i < n; i++) 21 for(int j = 0; j < m; j++) 22 scanf("%d", &cost[i][j] ); 23 memset( dp, 0x3f, sizeof dp ); 24 for(int i = 0; i < m; i++) 25 dp[0][i] = cost[0][i], way[0][i] = i; 26 for(int i = 1; i < n; i++){ 27 dp[i][0] = dp[i-1][0]+cost[i][0]; 28 way[i][0] = (i-1)*m; 29 for(int j = 1; j < m; j++){ 30 int t1=dp[i-1][j]+cost[i][j]; 31 int t2=dp[i][j-1]+cost[i][j]; 32 if( t1<t2 ) 33 dp[i][j] = t1, way[i][j] = (i-1)*m + j; 34 else 35 dp[i][j] = t2, way[i][j] = i*m + (j-1); 36 } 37 for(int j = m-2; j >= 0; j-- ){ 38 if( dp[i][j] > (dp[i][j+1]+cost[i][j]) ) 39 dp[i][j] = dp[i][j+1]+cost[i][j], way[i][j] = i*m + (j+1); 40 41 } 42 } 43 int Min = 1<<30, w; 44 for(int i = 0; i < m; i++){ 45 if( dp[n-1][i] < Min ) 46 Min = dp[n-1][i], w = i; 47 } 48 Print( n-1, w ); 49 } 50 return 0; 51 }