POJ 2029 Get Many Persimmon Trees(水题)

题意:在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\n", DP()); 
58     }
59     return 0;
60 }
View Code

 

posted @ 2013-11-18 15:41  Plumrain  阅读(225)  评论(0编辑  收藏  举报