POJ1050
题目链接:http://poj.org/problem?id=1050
题目描述:
首先求矩形区域和显然是使用前缀和。然后要求出最大区域和,则应想到动态规划。
先使用dp[r,c,w,h]表示以(r,c)为矩形右下角顶点时形状为(w,h)的矩形区域和,但这样时间空间复杂度过高,必须简化。
现在使用dp[c,w],更新顺序为r从1到n,c从1到n,w从1到c(或从c到1),dp[c,w]表示当前行r下,以(r,c)为矩形右下角顶点时,矩形占用w列时,区域和的最大值。这样时间复杂度为O(N3),空间复杂度为O(N2),是可行的。
更新法则为
int dp_row=sum[r][c]-sum[r][c-l]-sum[r-1][c]+sum[r-1][c-l];
dp[c][l]=max(dp_row,dp[c][l]+dp_row);
代码
#include <iostream>
#include <algorithm>
#define N 102
using namespace std;
int main()
{
int n;
int sum[N][N]={0};
//dp[C][L]
//以当前行C列处为矩形右下角顶点,占用L列时,矩形区最大和
int dp[N][N]={0};
cin>>n;
//矩形区域和-->二维前缀和
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
cin>>sum[i][j];
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
sum[i][j]+=sum[i-1][j]+sum[i][j-1]-sum[i-1][j-1];
//初始化
int max_val=-n*n*128;
for(int c=1;c<=n;c++)
for(int l=1;l<=c;l++)
dp[c][l]=sum[1][c]-sum[1][c-l];
//第一行已经初始化了,从第二行开始
//从上到下,从左到右,从1到c遍历l,扫描
for(int r=2;r<=n;r++)
for(int c=1;c<=n;c++)
for(int l=1;l<=c;l++)
{
int dp_row=sum[r][c]-sum[r][c-l]-sum[r-1][c]+sum[r-1][c-l];
dp[c][l]=max(dp_row,dp[c][l]+dp_row);
max_val=max(max_val,dp[c][l]);
}
cout<<max_val<<endl;
}
转载:https://blog.csdn.net/qq_36393962/article/details/82846432