洛谷p1006傳紙條

原題

不能每次選最大的走(貪心),因爲有可能小的後面接大的,比如

0   1   99

12 10 1

由於只能想兩個方向走,所以到達結果的步數是固定的(長+寬-1)

但是用步數不能表達狀態,所以就用座標表示f[i][j]表示在(i,j)最大的和,轉移方程有反方向得來

要求來回且路線不能重合,那麼用f[i][j][k][z]表示第一次在(i,j),第二次在(k,z)的最優解

雖然起始點不同,但無所謂,可以看爲相同起始點,還可以壓縮一維,畢竟第一次和第二次是同時轉換的,他們的步數相同。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<iomanip>
#include<algorithm>
using namespace std;
int m,n,a[51][51],f[51][51][51][51];
int main()
{
    cin>>m>>n;
    for(int i=1;i<=m;++i)
     for(int j=1;j<=n;++j)
      cin>>a[i][j];
    for(int i=m;i>=1;--i)
     for(int j=n;j>=1;--j)
      for(int k=m;k>=1;--k)
       for(int z=n;z>=1;--z)
       f[i][j][k][z]=0;
    for(int i=m;i>=1;--i)
     for(int j=n;j>=1;--j)
      for(int k=m;k>=1;--k)
       for(int z=n;z>=1;--z)
        {
            if((i>1&&k>1)&&(i-1!=k-1||j!=z)) f[i-1][j][k-1][z]=max(f[i-1][j][k-1][z],f[i][j][k][z]+a[i-1][j]+a[k-1][z]);
            if((i>1&&z>1)&&(i-1!=k||j!=z-1)) f[i-1][j][k][z-1]=max(f[i-1][j][k][z-1],f[i][j][k][z]+a[i-1][j]+a[k][z-1]);
            if((j>1&&k>1)&&(i!=k-1||j-1!=z)) f[i][j-1][k-1][z]=max(f[i][j-1][k-1][z],f[i][j][k][z]+a[i][j-1]+a[k-1][z]);
            if((j>1&&z>1)&&(i!=k||j-1!=z-1)) f[i][j-1][k][z-1]=max(f[i][j-1][k][z-1],f[i][j][k][z]+a[i][j-1]+a[k][z-1]);
        }
    cout<<f[2][1][1][2];
    return 0;
}





發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章