今天做了一道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;
}
};