【问题标题】:Can any identify the mistake in my algorithm?任何人都可以识别我的算法中的错误吗?
【发布时间】:2016-03-10 20:11:02
【问题描述】:

问题陈述是这样的

给定一个二进制矩阵,找出最大尺寸全为 1 的子矩阵。

例如,考虑下面的二进制矩阵。

   0  1  1  0  1 
   1  1  0  1  0 
   0  1  1  1  0
   1  1  1  1  0
   1  1  1  1  1
   0  0  0  0  0

所有设置位的最大平方子矩阵为3

我创建了一个基于记忆的 dp 解决方案

我的程序是

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

#define R 6
#define C 5

int getmaxsizesummatrix(int mat[R][C],vector< vector<int> > &v,int r,int c)
{
    if(r<0||c<0)
        return 0;

    if(r==0||c==0)
    {
        v[r][c]=mat[r][c];
         return mat[r][c];
    }


    if(v[r][c]==-1)
    {
    int m=INT_MIN;
    int flag=1;
        for(int j=0;j<=r;j++)
        {
            for(int k=0;k<=c;k++)
            {

                int x,y,z;
                x = getmaxsizesummatrix(mat,v,j-1,k-1);
                y = getmaxsizesummatrix(mat,v,j-1,k);
                z = getmaxsizesummatrix(mat,v,j,k-1);



                if(mat[j][k]==1)
                {
                m=max(m,min(x,min(y,z))+1);
                }
                else
                {    
                 m=max(m,min(x,min(y,z)));   
                }
            }
        }
    return v[r][c] = m;
    }
    else
    {
        return v[r][c];
    }
}

int main()
{
    int M[R][C] = {{0, 1, 1, 0, 1},
                   {1, 1, 0, 1, 0},
                   {0, 1, 1, 1, 0},
                   {1, 1, 1, 1, 0},
                   {1, 1, 1, 1, 1},
                   {0, 0, 0, 0, 0}};
    vector< vector<int> > v(R+1,vector<int>(C+1,-1));
  cout<<getmaxsizesummatrix(M,v,6,5);
  return 0;
}

我得到 4 作为输出。

谁能纠正我的方法???

【问题讨论】:

  • 练习 CodeJam?
  • 请使用调试器,一步一步检查你的变量内容......这将比在这里发布你的代码更有效。
  • learning dp..not for codejam @MarwanAlani
  • 我在 ideone.com 中运行您的代码并给我 5 而不是 4...

标签: c++ algorithm matrix dynamic-programming


【解决方案1】:

我已经稍微修改了你的代码以使其正常工作

这里是解释:你在实施 DP 解决方案时有 2 个问题

  1. dp 向量的定义v[][]
  2. 您将自下而上和自上而下的实现混为一谈,让调试变得更加困难

对于&lt; 与&lt;= 作为提到的另一个答案,这在您的实现中不是问题,因为它是上面第2点所述的异常实现,但您必须通过R-1 & C-1 改为函数,因此您仍然可以计算 v[r][c] 而不会超出范围

我将重点关注以上两点。

对于1,你能告诉我你对v[][]的定义是什么吗? 是目前找到的最大正方形长度还是正方形的右下角为(i,j)的最大正方形长度?这是一个巨大的选择差异,当您使用v[][] 递归计算另一个v[][] 时,您应该采用第二个选项,这是我为您修改的代码的一部分。例如,您的代码将在v[1][2] &amp; v[1][4](从0 开始)处给出1,而我的代码将给出0,因为mat[1][2] &amp; mat[1][4] 是0,并且不能形成任何正方形。修改后,现在你的代码将计算v[][],它采用第二个定义,所以我们必须循环整个v[][]来得到答案,而不是简单地打印v[R][C]

对于 2,您的实施有点混乱,因为您混合了自下而上和自上而下的实施。换句话说,你把 for-loop 迭代 和 recursion 混为一谈了,对于包括这个在内的大多数 DP 问题,你只需要选择其中一种方法而不是两种方法。您正在尝试递归方法,该方法调用 Function(R,C) 来获得答案,但在每次调用中,您每次都循环遍历数组,这是冗余且容易出错的。你应该

  1. 自下而上:根本不使用函数,不使用递归,只需设置基本情况(第 1 行),并使用代码中显示的两个 for 循环来构建 v[][] 从小索引到大索引李>
  2. 自上而下:使用递归,递归函数内没有 for 循环!!只需用基本情况编写类似Func(R,C) = max(Func(R-1,C-1), Func(R-1,C), Func(R,C-1))+1 的内容来保护负索引,已经计算出v[r][c] 等。

请看一下代码,如果有什么遗漏或不清楚的地方告诉我,如果需要我会解释更多。

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

#define R 6
#define C 5

int getmaxsizesummatrix(int mat[R][C],vector< vector<int> > &v,int r,int c)
{
    if(r<0||c<0)
        return 0;

    if(r==0||c==0)
    {
        v[r][c]=mat[r][c];
         return mat[r][c];
    }


    if(v[r][c]==-1)
    {
		int m=INT_MIN;
        for(int j=0;j<=r;j++)
        {
            for(int k=0;k<=c;k++)
            {
                int x,y,z;
            	x = getmaxsizesummatrix(mat,v,j-1,k-1);
            	y = getmaxsizesummatrix(mat,v,j-1,k);
            	z = getmaxsizesummatrix(mat,v,j,k-1);
             
			
                if(mat[j][k]==1)
                {
                	m=max(m,min(x,min(y,z))+1);
                }
                else
                {    
                 	m=max(m,min(x,min(y,z)));   
                }
            }
        }
        if(mat[r][c] == 0) return v[r][c] = 0; // <-- Add this line
        return v[r][c] = m;
    	
    }
    else
    {
        return v[r][c];
    }
}

int main()
{
    int M[R][C] = {{0, 1, 1, 0, 1},
                   {1, 1, 0, 1, 0},
                   {0, 1, 1, 1, 0},
                   {1, 1, 1, 1, 0},
                   {1, 1, 1, 1, 1},
                   {0, 0, 0, 0, 0}};
   vector< vector<int> > v(R+1,vector<int>(C+1,-1));
  
  getmaxsizesummatrix(M,v,R-1,C-1);  // <-- Change Parameter
  

  // Change the answer-optain code 
  int ans = INT_MIN;
  for(int i=0; i<R; i++) 
  	for(int j=0; j<C;j++) ans = max(ans, v[i][j]);
  
  cout << ans << endl;
  return 0;
}

【讨论】:

  • 感谢@shole 的回答和很好的解释。
  • @sai 没问题,很高兴能帮到你:)
【解决方案2】:

不确定,但从外观上看 - 你差了一个。

注意:

#define R 6
#define C 5
...
int M[R][C] = {...};
getmaxsizesummatrix(M,v,6,5); 
...
int getmaxsizesummatrix(int mat[R][C],vector< vector<int> > &v,int r,int c) // r=6, c=5
{
    ...
    for(int j=0;j<=r;j++)
    {
        for(int k=0;k<=c;k++)
        {
             ...
        }
    }
}

也许解决方案是严格检查j&lt;r 而不是j&lt;=r。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-06-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-11-10
    • 2020-12-30
    相关资源
    最近更新 更多