noip2008 传纸条

 

noip2008 传纸条

 

传纸条是就是双线问题,这类题目还有经典的方格取数问题。通常遇到这种问题,可以选择加维和增加状态判断解决。

 

我把从上走到下和从下走到上,看做是两条线从上往下走。

 

其中加入一个判断条件就是两个点不能从一个相同的点走过来。这样即使他们目前是走到相同的点,那么这个状态以后不会被用到。而到终点的时候就不会冲突了。

 

我要表示两个点的位置需要两个坐标。那么我需要DP[A][B][C][D]这样一个四维的数组来保存。空间上也许会不允许。

 

认真想想,就会发现,我要求两条线一起走,也就是说每一次状态两条线走的步数 k 是一样的,而我只要知道横坐标 x 就可以得到纵坐标 k - x

 

这样我们只需要一个三维的数组就够了 dp[a][b][c]

 

 

每个状态都有四种选择。分别是

 

1.a是从左边走来  b是从左边

2.a    上面           左边

3.a    左边           右边

4.a    右边           右边

 

用坐标相应的表示就行了。

 

 

#include using namespace std; int main() { int m,n; int map[50][50],dp[100][50][50]; cin >> m >> n; for( int i = 0;i < m;++i ) { for( int j = 0;j < n;++j ) cin >> map[i][j]; } dp[0][0][0] = 0; dp[1][0][1] = map[0][1] + map[1][0]; dp[1][1][0] = map[0][1] + map[1][0]; for( int k = 2;k < m+n-1;++k ) { for( int i = 0;i < m && i <= k;++i ) { for( int j = 0;j < m && j <= k;++j ) { int max = -1; if( j-1 >= 0 && !( i == j-1 && k-1-i == k-1-(j-1) ) ) { if( dp[k-1][i][j-1] + map[i][k-i] + map[j][k-j] > max ) max = dp[k-1][i][j-1] + map[i][k-i] + map[j][k-j]; } if( i-1 >= 0 && j-1 >= 0 && !( i-1 == j-1 && k-1-(i-1) == k-1-(j-1) ) ) { if( dp[k-1][i-1][j-1] + map[i][k-i] + map[j][k-j] > max ) max = dp[k-1][i-1][j-1] + map[i][k-i] + map[j][k-j]; } if( !( i == j && k-1-i == k-1-j ) ) { if( dp[k-1][i][j] + map[i][k-i] + map[j][k-j] > max ) max = dp[k-1][i][j] + map[i][k-i] + map[j][k-j]; } if( i-1 >= 0 && !( i-1 == j && k-1-(i-1) == k-1-j ) ) { if( dp[k-1][i-1][j] + map[i][k-i] + map[j][k-j] > max ) max = dp[k-1][i-1][j] + map[i][k-i] + map[j][k-j]; } dp[k][i][j] = max; //cout << dp[k][i][j] << ' '; } //cout << endl; } //cout << endl; } cout << dp[m+n-2][m-1][m-1] << endl; //system("pause"); return 0; } 

你可能感兴趣的:(动态规划)