//方法一:暴力枚举法
//直接求两个点之间所有数的和
//优点:简单易懂
//缺点:超时
class Solution {
public:
struct Point
{
int x; //点的横坐标
int y; //点的纵坐标
};
int sumMatrix(Point f, Point e, vector<vector<int>> &matrix)
{
//起点到终点之间所有点求和
int temp = 0;
for(int i=f.x;i<= e.x;i++)
{
for(int j= f.y;j<= e.y;j++)
{
temp += matrix[i][j];
}
}
return temp;
}
int numSubmatrixSumTarget(vector<vector<int>> &matrix, int target)
{
int res = 0;
int hang = 0;
int lie = 0;
int temp = 0;
if (matrix.size() != 0)
{
hang = matrix.size(); //得到矩阵的行
if (matrix[0].size() != 0)
{
lie = matrix[0].size(); //得到矩阵的列
}
}
for (int i = 0; i < hang; i++)
{
for (int j = 0; j < lie; j++)
{
Point fP; //起点
fP.x = i;
fP.y = j;
for (int k = i; k < hang; k++)
{
for (int l = j; l < lie; l++)
{
Point eP; //终点
eP.x = k;
eP.y = l;
temp = sumMatrix(fP, eP, matrix); //求不规则矩阵的和与target比较
if (temp == target)
{
res++;
}
}
}
}
}
return res;
}
};
//有了上述经验后,我想了想,重复计算的值太多,能不能让其中有些值保留下来,为以后用,我观察到当控制起点不动时,终点的推移其实是有顺序的,从当起点先向右走,即每一行先从左到右,每一列从上到下。这便为某些值的重复利用做好铺垫!
//部分优化
class Solution {
public:
static int rtemp ; //起点对应行的右边的值
static int btemp ; //起点对应列下边的值
struct Point
{
int x;
int y;
};
int sumMatrix(Point f, Point e, vector<vector<int>> &matrix)
{
int temp=0;
int hang = e.x;
int lie = e.y;
if(f.x == e.x&&f.y == e.y){
rtemp=matrix[hang][lie];
btemp=matrix[hang][lie];
return matrix[hang][lie];
}
if (f.x == e.x)
{
return rtemp += matrix[hang][lie];
}
else if (f.y == e.y)
{
return btemp += matrix[hang][lie];
}
else
{
for (int i = f.x; i <= e.x; i++)
{
for (int j = f.y; j <= e.y; j++)
{
temp += matrix[i][j];
}
}
}
return temp;
}
int numSubmatrixSumTarget(vector<vector<int>> &matrix, int target)
{
int res = 0;
int hang = 0;
int lie = 0;
int temp = 0;
if (matrix.size() != 0)
{
hang = matrix.size();
if (matrix[0].size() != 0)
{
lie = matrix[0].size();
}
}
for (int i = 0; i < hang; i++)
{
for (int j = 0; j < lie; j++)
{
Point fP; //起点
fP.x = i;
fP.y = j;
for (int k = i; k < hang; k++)
{
for (int l = j; l < lie; l++)
{
Point eP; //终点
eP.x = k;
eP.y = l;
temp = sumMatrix(fP, eP, matrix);
if (temp == target)
{
res++;
}
}
}
}
rtemp=0;
btemp=0;
}
return res;
}
};
int Solution::rtemp =0; //起点对应行的右边的值
int Solution::btemp =0; //起点对应列下边的值
//但是,结果仍然不尽人意!!
这意味着我得重新思考这个问题了!!!
我注意到:以(0,0)为起点到其它点的数的和总是等于④=②+③-①+x;
④:该点到起点之间的点的和
x:终点处矩阵的值
此图是tMatrix,比原matrix多一行多一列,便于计算。
class Solution {
public:
struct Point
{
int x;
int y;
};
int numSubmatrixSumTarget(vector<vector<int>> &matrix, int target)
{
int res = 0;
int hang = 0;
int lie = 0;
int temp = 0;
if (matrix.size() != 0)
{
hang = matrix.size();
if (matrix[0].size() != 0)
{
lie = matrix[0].size();
}
}
for (int i = 0; i < hang; i++)
{
for (int j = 0; j < lie; j++)
{
Point f; //起点
f.x = i;
f.y = j;
vector<vector<int>> tMatrix(hang-i+1, vector<int>(lie-j+1, 0));
for (int k = i; k < hang; k++)
{
for (int l = j; l < lie; l++)
{
Point e; //终点
e.x = k;
e.y = l;
int temp=tMatrix[e.x-f.x][e.y+1-f.y]+tMatrix[e.x+1-f.x][e.y-f.y]-tMatrix[e.x-f.x][e.y-f.y]+matrix[e.x][e.y];
tMatrix[e.x+1-f.x][e.y+1-f.y]=temp;
if (temp == target)
{
res++;
}
}
}
}
}
return res;
}
};
//但是还是超时!!!
//我最后想了一种其他的方法
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <vector>
#define _for(i, a, b) for (int i = a; i < b; i++)
using namespace std;
//打印矩阵,便于验证
// void printMatrix(int hfirst,int flie,int hang, int lie, vector<vector<int>> &m)
// {
// for (int k = hfirst; k < hang; k++)
// {
// for (int l = flie; l < lie; l++)
// {
// cout << m[k][l] << " ";
// }
// cout << endl;
// }
// }
int numSubmatrixSumTarget(vector<vector<int>> &matrix, int target)
{
int res = 0; //矩阵中任意值等于target的个数
int hang = 0; //输入矩阵的行
int lie = 0; //输入矩阵的列
int temp = 0; //临时判断
/*判断输入矩阵的行和列*/
if (matrix.size() != 0)
{
hang = matrix.size();
if (matrix[0].size() != 0)
{
lie = matrix[0].size();
}
}
// cout << "matrix----------------" << endl;
// printMatrix(0,0,hang,lie,matrix);
// cout << "------------------------------------------" << endl;
//tMartix记录起点到终点的和的矩阵
vector<vector<int>> tMatrix(hang + 1, vector<int>(lie + 1, 0));
//对tMatrix的复制
vector<vector<int>> ttMatrix(hang + 1, vector<int>(lie + 1, 0));
//将矩阵全部清为0
vector<vector<int>> tttMatrix(hang + 1, vector<int>(lie + 1, 0));
int num = hang * lie; //矩阵个数
int i = 0; //矩阵行的起始坐标
int j = 0; //矩阵列的起始坐标
while (num)
{
//cout << "行=" << i << " 列=" << j << endl;
if (i == j) //当起点坐标在对角线上,将其全部清空,因为要重新计算起点到终点的和的矩阵
{
tMatrix = tttMatrix; //清空
for (int k = i; k < hang; k++)
{
for (int l = j; l < lie; l++)
{
temp = tMatrix[k][l + 1] + tMatrix[k + 1][l] - tMatrix[k][l] + matrix[k][l];
tMatrix[k + 1][l + 1] = temp;
if (temp == target)
{
res++;
}
}
}
//printMatrix(i+1,j+1,hang+1,lie+1,tMatrix);
ttMatrix = tMatrix; //复制
j++; //先水平移动
if (lie - j <= 0) //当移动到矩阵最右边时,终点坐标移动到起点坐标的下面
{
j = i;
i++;
}
}
else if (j > i)
{
for (int k = i; k < hang; k++)
{
for (int l = j; l < lie; l++)
{
temp = tMatrix[k + 1][l + 1] - tMatrix[k + 1][j];
tMatrix[k + 1][l + 1] = temp;
if (temp == target)
{
res++;
}
}
}
//printMatrix(i+1,j+1,hang+1,lie+1,tMatrix);
j++;
if (lie - j <= 0)
{
j = i;
i++;
tMatrix = ttMatrix;
}
}
else
{
for (int k = i; k < hang; k++)
{
for (int l = j; l < lie; l++)
{
temp = tMatrix[k + 1][l + 1] - tMatrix[i][l + 1];
tMatrix[k + 1][l + 1] = temp;
if (temp == target)
{
res++;
}
}
}
//printMatrix(i+1,j+1,hang+1,lie+1,tMatrix);
i++;
if (hang - i <= 0)
{
j++;
i = j;
}
}
num--;
//cout << "结果等于target的个数=" << res << endl;
}
return res;
}
//
int main()
{
freopen("D:\\xx.txt", "r", stdin);
int hang = 5;
int lie = 5;
vector<vector<int>> v(hang, vector<int>(lie));
for (int i = 0; i < hang; i++)
{
for (int j = 0; j < lie; j++)
{
cin >> v[i][j];
}
}
cout << numSubmatrixSumTarget(v, 0);
//system("pause");
return 0;
}
附上xx.txt文件
0 0 0 1 1
1 1 1 0 1
1 1 1 1 0
0 0 0 1 0
0 0 0 1 1
下图红色代表,当i大于j时的情形
下图蓝色的是j大于i的情况
整体遍历顺序是
耗时十多个小时,真的累呀!