#include <iostream>
#include <vector>
#include <stack>
using namespace std;
int uniquePaths(int m, int n)
{
vector<vector<int>>dp(m,vector<int>(n));
for(int i = 0;i < m; ++i)
{
dp[i][0] = 1;
}
for(int i = 0; i < n; ++i)
{
dp[0][i] = 1;
}
for(int i = 1; i < m; ++i)
{
for(int j = 1; j < n ; ++j)
{
dp[i][j] = dp[i-1][j] + dp[i][j-1];
}
}
return dp[m-1][n-1];
}
int uniquePathsI(int m, int n)
{
vector<int>dp(n,1);
for(int i = 1; i < m; ++i)
{
for(int j = 1; j < n; ++j)
{
dp[j] = dp[j] + dp[j-1];
}
}
return dp[n-1];
}
int uniquePaths(const vector<vector<int>>paths)
{
int m = paths.size(), n = paths[0].size();
vector<vector<int>>dp(m,vector<int>(n));
for(int i = 0; i < m; ++i)
{
if(paths[i][0] == 1)
break;
dp[i][0] = 1;
}
for(int i = 0;i < n; ++i)
{
if(paths[0][i] == 1)
break;
dp[0][i] = 1;
}
for(int i = 1;i < m; ++i)
{
for(int j = 1; j < n; ++j)
{
dp[i][j] = paths[i][j]== 1 ? 0 : dp[i-1][j] + dp[i][j-1];
}
}
return dp[m-1][n-1];
}
int minimmTotal(const vector<vector<int>>& triangle)
{
int n = triangle.size();
vector<vector<int>>dp(n+1,vector<int>(n+1,0));
for(int i = n-1; i >= 0 ;--i)
{
for(int j = i; j >= 0; --j)
{
dp[i][j] = min(dp[i+1][j],dp[i+1][j+1])+triangle[i][j];
}
}
return dp[0][0];
}
int minPathSum(vector<vector<int>>& grid)
{
int m = grid.size(), n = grid[0].size();
for(int i = 0; i < m; ++i)
{
for(int j = 0; j < n; ++j)
{
if(i == 0)grid[i][j] += grid[i][j-1];
else if(j == 0)grid[i][j] += grid[i-1][j];
else
grid[i][j]+=min(grid[i-1][j],grid[i][j-1]);
}
}
return grid[m-1][n-1];
}
int minFallingPathSum(vector<vector<int>>& A)
{
int m = A.size(), n = A[0].size();
for(int i = m - 2; i >= 0; --i)
{
for(int j = 0;j < n; ++j)
{
int minVal = A[i+1][j];
if(j > 0)minVal = min(minVal,A[i+1][j-1]);
if(j+1 < n)minVal = min(minVal,A[i+1][j+1]);
A[i][j]+=minVal;
}
}
sort(A[0].begin(),A[0].end());
return A[0][0];
}
int minFallingPathSumI(vector<vector<int>>& grid)
{
int m = grid.size(), n = grid[0].size();
vector<vector<int>>dp(m,vector<int>(n));
for(int i = 0;i < n ; ++i)dp[0][i] = grid[0][i];
for(int i = 1; i < m; ++i)
{
for(int j = 0; j < n; ++j)
{
int preRowMin = INT_MAX;
for(int k = 0; k < n; ++k)
{
if(j != k) preRowMin = min(preRowMin,dp[i-1][k]);
dp[i][j] = grid[i][j] + preRowMin;
}
}
}
int res = INT_MAX;
for(int i = 0;i < n ; ++i)
{
res = min(res,dp[m-1][i]);
}
return res;
}
int maxSuqare(const vector<vector<string>>& matrix)
{
int m = matrix.size(), n = matrix[0].size();
int maxVal = INT_MIN;
vector<vector<int>>dp(m,vector<int>(n));
for(int i = 0; i < m; ++i)
{
for(int j = 0; j < n; ++j)
{
if(i == 0 || j == 0)
{
if(matrix[i][j] == "1")dp[i][j] = 1;
}
else
{
if(matrix[i][j] == "1")
dp[i][j] = min(dp[i-1][j],min(dp[i][j-1],dp[i-1][j-1])) + 1;
}
maxVal = max(maxVal,dp[i][j]);
}
}
return maxVal*maxVal;
}
int largestRectangle(vector<int>& height)
{
stack<int>st;
int res = 0;
for(int i = 0; i < height.size(); ++i)
{
while(!st.empty() && height[i] <= height[st.top()])
{
int preHeight = height[st.top()];
st.pop();
int width = i - (st.empty() ? 0:st.top() + 1);
res = max(res,preHeight * width);
}
st.push(i);
}
while(!st.empty())
{
int preHeight = height[st.top()];
st.pop();
int width = height.size() - (st.empty() ? 0 :st.top() + 1);
res = max(res,preHeight * width);
}
return res;
}
int maxRectangle(const vector<vector<string>>& matrix)
{
int m = matrix.size();
if(m == 0)return 0;
int n = matrix[0].size();
vector<int>height(n);
int res = 0;
for(int i = 0; i < m; ++i)
{
for(int j = 0;j < n; ++j)
{
if(matrix[i][j] == "0")height[j]=0;
else ++height[j];
}
res = max(res,largestRectangle(height));
}
return res;
}
int main()
{
//LeetCode62
cout << uniquePaths(3,2) << endl;
cout << uniquePathsI(3,2) << endl;
//LeetCode63
// vector<vector<int>>paths{{0,0,0},{0,1,0},{0,0,0}};
vector<vector<int>>paths{{0,1},{0,0}};
cout << uniquePaths(paths) << endl;
//LeetCode120
vector<vector<int>>triangle={{2},{3,4},{6,5,7},{4,1,8,3}};
cout << minimmTotal(triangle) << endl;
//LeetCode64
vector<vector<int>>grid{{1,3,1},{1,5,1},{4,2,1}};
cout << minPathSum(grid) << endl;
//LeetCode931
vector<vector<int>>grids{{1,2,3},{4,5,6},{7,8,9}};
// cout << minFallingPathSum(grids) << endl;
//LeetCode1289
cout << minFallingPathSumI(grids) << endl;
//LeetCode221
vector<vector<string>>matrix{{"1","0","1","0","0"},{"1","0","1","1","1"},{"1","1","1","1","1"},{"1","0","0","1","0"}};
cout << maxSuqare(matrix) << endl;
//LeetCode85
cout << maxRectangle(matrix) << endl;
return 0;
}