今天做了一道dp的题,感觉和今年中科大夏令营上机题神似,题目如下(来自leetcode):
我的思路是设置一个二维数组dp,来保存一些信息。这个dp[i][j]保存的是什么呢?是以点 (i,j) 为正方形右下角顶点所能组成的正方形变成。例如上图的示例1,有:
dp=
[
[0,1,1,1],
[1,1,2,2],
[0,1,2,3]
]
那么我们最终要计算的的就是数组dp的和。因此问题转化成了如何求dp。
当 matrix[i][j] == 0,显然 dp[i][j] == 0,因为如果以点 (i,j) 为一个正方形的右下角,肯定是构不成正方形的;
当 matrix[i][j] == 1,且i == 0或j == 0时,dp[i][j]==1;
当 matrix[i][j] == 1,且i > 0和j > 0时,需要从点 (i,j) 出发,向上和左方向去搜索 dp[i-1][j-1] 个单位,如果遇到0则跳出,反之不断加1。
AC代码如下:
class Solution {
public:
int countSquares(vector<vector<int>>& matrix) {
int n = matrix.size();
int m = matrix[0].size();
vector<vector<int>> dp(n,vector<int>(m,0));
int cnt = 0;
for(int i=0;i<n;i++)
{
for(int j=0;j<m;j++)
{
//原矩阵数值为0,则dp为0
if(matrix[i][j]==0)
{
dp[i][j] = 0;
}
//原矩阵数值为1,先令dp为1
else if(matrix[i][j]==1)
{
dp[i][j] = 1;
}
//如果原矩阵点的值为1,且该点上侧和左侧非空
if(i>=1&&j>=1&&matrix[i][j]==1)
{
//分别向上和向左搜索dp[i-1][j-1]个单位
for(int k=1;k<=dp[i-1][j-1];k++)
{
//如果上侧和左侧的值都为1,则dp自增1
if(matrix[i-k][j]==1&&matrix[i][j-k]==1)
{
dp[i][j]++;
}
//遇到0跳出
else
{
break;
}
}
}
cnt += dp[i][j];
}
}
return cnt;
}
};