题意:在w*h(最大100*100)的棋盘上,有的格子中放有一棵树,有的没有。问s*t的小矩形,最多能含有多少棵树。
解法:最直接的想法,设d[x1][y1][x2][y2]表示选择以(x1, y1)为左下角,以(x2, y2)为右上角的矩形含有多少棵树。然后就可以很容易地递推了。可是空间复杂度为O(10^8)不能被接受。
又发现d[x1][y1][x2][y2] = d[1][1][x2][y2] - d[1][1][x1-1][y2] - d[1][1][x2][y1-1] + d[1][1][x1-1][y1-1],所以只需要预处理出所有的d[1][1][i][j]即可,然后每次求出一个d[x1][y1][x2][y2]就与ans比较,不用存下来。
tag:DP
1 /* 2 * Author: Plumrain 3 * Created Time: 2013-11-18 01:05 4 * File Name: DP-POJ-2029.cpp 5 */ 6 #include <iostream> 7 #include <cstdio> 8 #include <cstring> 9 #include <algorithm> 10 11 using namespace std; 12 13 #define CLR(x) memset(x, 0, sizeof(x)) 14 15 int n, w, h, s, t; 16 bool has[200][200]; 17 int d[2][2][105][105]; 18 19 void init() 20 { 21 scanf ("%d%d", &w, &h); 22 int t1, t2; 23 CLR (has); 24 for (int i = 0; i < n; ++ i){ 25 scanf ("%d%d", &t1, &t2); 26 has[t1][t2] = 1; 27 } 28 scanf ("%d%d", &s, &t); 29 } 30 31 int DP() 32 { 33 int ret = 0; 34 CLR (d); 35 ret = d[1][1][1][1] = has[1][1]; 36 for (int i = 2; i <= w; ++ i) 37 d[1][1][i][1] = d[1][1][i-1][1] + has[i][1]; 38 for (int i = 2; i <= h; ++ i) 39 d[1][1][1][i] = d[1][1][1][i-1] + has[1][i]; 40 41 for (int i = 2; i <= w; ++ i) 42 for (int j = 2; j <= h; ++ j) 43 d[1][1][i][j] = has[i][j] + d[1][1][i-1][j] + d[1][1][i][j-1] - d[1][1][i-1][j-1]; 44 45 for (int x1 = 1; x1 <= w; ++ x1) 46 for (int y1 = 1; y1 <= h; ++ y1) 47 for (int x2 = x1; x2 <= min(x1+s-1, w); ++ x2) 48 for (int y2 = y1; y2 <= min(y1+t-1, h); ++ y2) 49 ret = max(ret, d[1][1][x2][y2] - d[1][1][x1-1][y2] - d[1][1][x2][y1-1] + d[1][1][x1-1][y1-1]); 50 return ret; 51 } 52 53 int main() 54 { 55 while (scanf ("%d", &n) != EOF && n){ 56 init(); 57 printf ("%d ", DP()); 58 } 59 return 0; 60 }