【问题标题】:Using a 2-d Array in a function在函数中使用二维数组
【发布时间】:2015-03-19 23:31:28
【问题描述】:

我正在尝试解决动态编程问题,我需要以二维数组的形式获取用户输入,并在函数内部使用二维数组中的值。 二维数组的值在函数内部使用时不会改变。

在函数 int dp 中,我得到了 错误:

将“a”声明为多维数组必须对除第一个维度之外的所有维度都有边界

int max(int a,int b,int c)
{
if(a>=b && a>=c)return a;
if(b>=c && b>=a)return b;
else return c;
}
int max2(int a,int b)
{
if(a>b)return a;
else return b;

}


int dp(int i,int j,int a[][],int p,int q)
{
if((i-1)>=0 && (j-1)>=0 &&(i+1)<p &&(j+1)<q )
return  max(a[i][j]+dp(i-1,j+1,a,p,q),a[i][j]+dp(i+1,j+1,p,q),    
    a[i][j]+dp(i,j+1,p,q));
if(i==0 && j!=0 && (j+1)<q)
return max2(a[i][j]+dp(i+1,j+1,p,q),a[i][j]+dp(i,j+1,p,q));

}
int main()
{
int p,q,r,s,T,a,b,i,j,k;
scanf("%d",&T);
for(a=0;a<T;a++)
{
    scanf("%d %d",p,q);
    int z[p][q];
    int max=0;
    for(i=0;i<q;i++)
    {
        for(j=0;j<p-1;j++)
        scanf("%d ",&z[j][i]);
        scanf("%d",&z[j+1][i]);
    }
    for(i=0;i<p;i++)
   {
    if(dp(i,0,z,p,q)>max)
    max=dp(i,0,z,p,q);
   }

  }

   }

【问题讨论】:

  • 1) 变量名使用多个字母。 2) 如果这是 C++,那么为什么不使用标准容器,例如 std::vector

标签: c++ arrays recursion multidimensional-array dynamic-programming


【解决方案1】:

都在错误信息中:

将“a”声明为多维数组必须对除第一个维度之外的所有维度都有边界

您的函数签名没有a 的第二维边界:

int dp(int i,int j,int a[][],int p,int q)
//                     ^^^^^

您需要用a[][N] 填写它,其中N 是正确的界限。问题是您在这里使用 VLA:

scanf("%d %d",p,q);
int z[p][q];

那是非标准的 C++,基本上意味着你不能写 dp 的签名,因为第二个边界必须被称为编译时常量。您可以将其设为一维数组:

int* z = new int[p*q];

int dp(int i, int j, int* a, int p, int q)
//                   ^^^^^^

或在二维中动态分配它并以这种方式传递它:

int** z = new int*[p];
for (int i = 0; i < p; ++i) {
    z[i] = new int[q];
}

int dp(int i, int j, int** a, int p, int q)
//                   ^^^^^^^

【讨论】:

    【解决方案2】:

    函数dp 需要一些信息来执行有意义的索引计算,要么由编译器完成,要么在实际实现中完成。必须在类型中指定维度,或者参数a 可以是int** 类型,而其维度作为单独的参数提供给dp。由于这是 C++,std::vector&lt; std::vector&lt; int &gt; &gt; 的类型可能更适合该任务。

    【讨论】:

      【解决方案3】:

      您会收到该错误,因为您不能在函数声明中将 int a[][] 中的 index(row,column) 都留空。您必须同时指定或至少指定列索引的值。

      使用动态声明

      int **z = new int*[p];
      for (int i = 0; i < p; i++) 
          z[i] = new int[q];
      

      将参数int a[][]改为int **a

      【讨论】:

      • 我不能这样做,因为数组的尺寸必须从用户那里获取
      • 如果我对 int a[][] 执行 int a[p][q] 之类的操作,则会显示错误,即 p 和 q 是在此范围内声明的注释
      【解决方案4】:

      您不能在堆栈上动态声明数组,因为在编译时必须知道大小。这样做的唯一方法是使用new 关键字在堆上为数组分配内存,然后您可以在运行时声明大小。

      然而,更容易的是使用一个容器类,或者在你的情况下,一个容器的容器,比如一个整数向量的向量;

      #include <vector>
      
      vector< vector<int> > arrArray(rows, vector<int>(columns)); 
      

      语法可能看起来有点奇怪,但要分解一下;

      vector&lt;int&gt; - int 类型的向量

      vector&lt; vector&lt;int&gt; &gt; - int 类型向量的向量

      arrArray(rows, vector&lt;int&gt;(columns)); - 在第一个参数中,我们说的是;在我们的数组中创建rows 数量的vector&lt;int&gt;,第二个参数将数组初始化为某个值。如果它只是int 的二维数组,我们可能会将其初始化为0,或者省略第二个参数并依赖默认值int。但是,因为我们的多维向量也包含向量,所以我们将主向量的每一行设置为存储int 的向量,其中包含columns 的整数数量。

      现在您可以像访问其他数组一样访问该数组了;

      arrArray[2][0] = 5;
      

      您还可以获得容器类所包含的所有额外好处,包括迭代器和许多用于操作和检查数组的有用的类方法。一旦你理解了创建容器类的语法,你会发现它们比数组更容易使用。您也不必担心必须管理自己的内存,并且能够在访问向量元素之前进行边界检查。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-02-16
        • 2017-11-26
        • 1970-01-01
        • 2015-07-02
        • 1970-01-01
        • 2020-07-30
        相关资源
        最近更新 更多