Fork me on GitHub

棋盘从左上到右下最小初始值

题意大概是给定M×N的棋盘格,从左上到右下,只能向右或者向下走,每走一步需要加上棋盘格子内的数值(有正有负)。

需要随时保证当前的数值>=1。问初始需要最少的值是多少?

 

思路:

动态规划。用dp[i][j]代表当前最大的数值。首先求出dp[m][n],得出到达右下角的最优值。

然后再回溯求出从左上角到右下角的路径。然后为了随时保证路径上的值>=1,找到路径上最小的值。

如果最小值>=1,那么初始只需要0即可满足条件。如果最小值<0,假如为-5,那么初始值必须为6,才能随时保证路径上的值>=1。

 

测试用例

m =2,n=3

-2 -3 3

-5 -10 1

输出  6.

 

int mininit()
{
     int m,n;
     cin>>m>>n;
     vector<vector<int>>board(m+1,vector<int>(n+1,0));
     vector<vector<int>> dp(m+1,vector<int>(n+1,0));
     for(int i=0;i<m;i++)
     {
       for(int j =0;j<n;j++)
       {
     cin>>board[i+1][j+1];     
      }
    }
    dp[1][1]= board[1][1];
   
    for(int i=2;i<=n;i++)dp[1][i] = dp[1][i-1]+board[1][i];     
    for(int i=2;i<=m;i++)dp[i][1] = dp[i-1][1]+board[i][1];
                        
    for(int i =2;i<=m;i++)
    {
      for(int j=2;j<=n;j++)
      {
       dp[i][j] = max(dp[i-1][j],dp[i][j-1])+board[i][j];
      }
    } 
    int minv = dp[m][n];
    while(m!=1|| n!=1) //回溯找到路径
    {
      if( (dp[m][n]-board[m][n]) ==  dp[m-1][n]) m = m-1;//当前m n是由上一行m-1 n得来的 否则是由左边m n-1得来的
      else n = n-1; 
      minv = min(minv,dp[m][n]);//记录路径上最小值
    //  cout<<m<<" "<<n<<endl;
    }
    if(minv>=1)return 0;
    return 1-minv; 
}

 

posted @ 2017-08-27 22:27  hellowOOOrld  阅读(721)  评论(1编辑  收藏  举报