网格中的动态编程 - 为什么要创建自上而下的表?

时间:2015-01-24 06:53:58

标签: c++ dynamic-programming

我在Codechef上做了这个问题 http://www.codechef.com/PRVG2015/problems/PRVG154/

问题的总结是Alex从左上角开始,希望最大化总分,而Bob希望通过减去他的方式中的元素来最小化总分。 它们交替移动,并且它们只能选择前面选定元素的右侧或底部的元素。 在形成表时,可以看出if(i + j)%2 == 0那么该元素只能被Alex选中,否则,它只能被Bob选中。 因此,对于(i + j)%2 == 1,我们将A [i] [j]更改为-A [i] [j],以便稍后,我们只需添加元素,最小化或最大化,具体取决于指数。

我见过的所有解决方案似乎都是自上而下创建DP [n] [m]表,从右下角到左上角(逆序)(即从dp [n-1]开始) [m-1]到dp [0] [0])。为什么这样做? 我也试过从左上角到右下角,但它没有给出正确的解决方案,尽管逻辑看起来很好。

#include <bits/stdc++.h>
using namespace std;

int main() {

ios_base::sync_with_stdio(false);
cin.tie(NULL);

int t, n, m, A[500][500],i,j;
int dp[500][500];

cin>>t;

while(t--)
{
    cin>>m>>n;

    for(i=0;i<m;i++)
        for(j=0;j<n;j++)
            cin>>A[i][j];

    for(i=0;i<m;i++)
    {
        for(j=0;j<n;j++)
        {
            if((i+j)%2 == 1)
                A[i][j] = -1 * A[i][j];
        }
    }

    dp[0][0] = A[0][0];

    for(i=1;i<m;i++)
        dp[i][0] = dp[i-1][0] + A[i][0];

    for(j=1;j<n;j++)
        dp[0][j] = dp[0][j-1] + A[0][j];

    for(i=1;i<m;i++)
    {
        for(j=1;j<n;j++)
        {
            if((i+j)%2 == 0)
            {
                dp[i][j] = max(dp[i-1][j],dp[i][j-1]) + A[i][j];
            }
            else
            {
                dp[i][j] = min(dp[i-1][j], dp[i][j-1]) + A[i][j];
            }

        }
    }


    cout<<dp[m-1][n-1]<<"\n";

}

return 0;
}

0 个答案:

没有答案