直接暴力枚举所有子矩形至少需要O(n^4)的复杂度,显然这不是一个合理的解决方法。
上述方案忽略了矩形之间的联系,进行了过多不必要的计算。
实际上如果固定矩形的左右边界,则底边在i行的矩形内数值之和与底边在i-1行的矩形的关系为 f[i] = s[i] + max(0, f[i - 1]), s[i]表示当前行对应的数值之和。
本题枚举是切入口,通过枚举把所有矩形分成左右边界固定的矩形族,而后再进行动态规划,可降低复杂度至O(n^3)。
acm.hdu.edu.cn/showproblem.php?pid=10811 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 5 using namespace std; 6 typedef __int64 LL; 7 8 const int inf = 0x3f3f3f3f; 9 const int maxn = 100 + 10; 10 11 int n; 12 int s[maxn][maxn]; 13 14 int main(){ 15 while(~scanf("%d", &n)){ 16 memset(s, 0, sizeof s); 17 for(int i = 1; i <= n; i++) for(int j = 1; j <= n; j++) scanf("%d", &s[i][j]); 18 for(int i = 1; i <= n; i++) for(int j = 1; j <= n; j++) s[i][j] += s[i][j - 1]; 19 int ans = -inf; 20 for(int i = 1; i <= n; i++){ 21 //enumerate left boundary 22 for(int j = i; j <= n; j++){ 23 //enumerate right boundary 24 int pre = -inf; 25 for(int k = 1; k <= n; k++){ 26 //dynamic programming 27 pre = s[k][j] - s[k][i - 1] + max(0, pre); 28 ans = max(ans, pre); 29 } 30 } 31 } 32 printf("%d\n", ans); 33 } 34 return 0; 35 }
时间: 2024-10-04 19:31:11