LOJ#2668 書法家

題意:要在一張網格紙上畫出NOI圖形,使得所佔格子的權值和最大。c++

解:暴力DP便可...ide

從左往右,每一個字母均可以被劃分紅三塊,且每塊均可用上下兩維來表示。spa

因而一塊一塊的DP。考慮如何O(1)轉移。顯然只有N的中間那一塊很差轉移,別的都是直接轉移。code

N的三塊的兩個鏈接處之間,能夠枚舉必須持平的那個端點,另外一個用前綴最值。blog

N第二塊內部,考慮枚舉後一個矩形的上邊界,逐步擴展下邊界。此時發現每擴展一步,可能的決策集合會增長:左邊一格,下邊界爲剛擴展的那一格,上邊界在枚舉的上邊界以上的全部狀態。get

因而對於每一個下邊界,預處理出上邊界從上到下的一個前綴最值,加到決策集合裏取max便可。it

  1 #include <bits/stdc++.h>
  2 
  3 const int INF = 0x3f3f3f3f;
  4 
  5 #define g f[FLAG]
  6 #define h f[FLAG ^ 1]
  7 
  8 int f[2][510][155][155], FLAG, n, m;
  9 int s[155][510], p[510], temp[155][155];
 10 
 11 inline int getSum(int i, int l, int r) {
 12     if(l > r) return 0;
 13     return s[r][i] - s[l - 1][i];
 14 }
 15 
 16 inline void out() {
 17     for(int i = 1; i <= m; i++) {
 18         for(int up = 1; up <= n; up++) {
 19             for(int down = up; down <= n; down++) {
 20                 printf("%d ", g[i][up][down]);
 21             }
 22         }
 23         puts("");
 24     }
 25     puts("");
 26     return;
 27 }
 28 
 29 inline void outp() {
 30     printf("p : ");
 31     for(int i = 1; i <= m; i++) {
 32         printf("%d ", p[i]);
 33     }
 34     puts("");
 35     puts("");
 36     return;
 37 }
 38 
 39 int main() {
 40     //printf("%d \n", sizeof(f) / 1048576);
 41 
 42     scanf("%d%d", &n, &m);
 43     for(int i = 1; i <= n; i++) {
 44         for(int j = 1; j <= m; j++) {
 45             scanf("%d", &s[i][j]);
 46             s[i][j] += s[i - 1][j];
 47         }
 48     }
 49 
 50     FLAG = 1; /// N 1
 51     memset(g, ~0x3f, sizeof(g));
 52     for(int i = 1; i <= m; i++) {
 53         for(int up = 1; up < n; up++) {
 54             for(int down = up + 1; down <= n; down++) {
 55                 g[i][up][down] = std::max(0, g[i - 1][up][down]) + getSum(i, up, down);
 56             }
 57         }
 58     }
 59 
 60     //out();
 61 
 62     FLAG ^= 1; /// N 1.5
 63     memset(g, ~0x3f, sizeof(g));
 64     for(int i = 1; i <= m; i++) {
 65         for(int up = 1; up < n; up++) {
 66             int large = -INF;
 67             for(int down = n - 1; down >= up; down--) {
 68                 large = std::max(large, h[i - 1][up][down + 1]);
 69                 g[i][up][down] = large + getSum(i, up, down);
 70             }
 71         }
 72     }
 73 
 74     //out();
 75 
 76     FLAG ^= 1; /// N 2
 77     //memset(g, ~0x3f, sizeof(g));
 78     memcpy(g, h, sizeof(h));
 79     for(int i = 1; i <= m; i++) {
 80         memset(temp, ~0x3f, sizeof(temp));
 81         for(int down = 1; down <= n; down++) {
 82             for(int up = 1; up <= down; up++) {
 83                 temp[down][up] = std::max(temp[down][up - 1], std::max(g[i - 1][up][down], h[i - 1][up][down]));
 84             }
 85         }
 86         for(int up = 1; up <= n; up++) {
 87             int large = temp[up - 1][up - 1];
 88             for(int down = up; down <= n; down++) {
 89                 large = std::max(large, temp[down][up]);
 90                 g[i][up][down] = std::max(large + getSum(i, up, down), h[i][up][down]);
 91             }
 92         }
 93     }
 94 
 95     //out();
 96 
 97     FLAG ^= 1; /// N 2.5
 98     memset(g, ~0x3f, sizeof(g));
 99     for(int i = 1; i <= m; i++) {
100         for(int down = 2; down <= n; down++) {
101             int large = -INF;
102             for(int up = down - 1; up >= 1; up--) {
103                 large = std::max(large, h[i - 1][up + 1][down]);
104                 g[i][up][down] = large + getSum(i, up, down);
105             }
106         }
107     }
108 
109     //out();
110 
111     FLAG ^= 1; /// N 3
112     memset(g, ~0x3f, sizeof(g));
113     for(int i = 1; i <= m; i++) {
114         for(int up = 1; up < n; up++) {
115             for(int down = up + 1; down <= n; down++) {
116                 g[i][up][down] = std::max(h[i][up][down], g[i - 1][up][down] + getSum(i, up, down));
117             }
118         }
119     }
120 
121     //out();
122 
123     /// get p : max of g
124     memset(p, ~0x3f, sizeof(p));
125     for(int i = 1; i <= m; i++) {
126         p[i] = p[i - 1];
127         for(int up = 1; up <= n; up++) {
128             for(int down = 1; down <= n; down++) {
129                 p[i] = std::max(p[i], g[i][up][down]);
130             }
131         }
132     }
133 
134     //outp();
135 
136     //out();
137 
138     //printf(" O 1 \n");
139 
140     FLAG ^= 1; /// O 1
141     memset(g, ~0x3f, sizeof(g));
142     for(int i = 5; i <= m; i++) {
143         for(int up = 1; up < n - 1; up++) {
144             for(int down = up + 2; down <= n; down++) {
145                 g[i][up][down] = p[i - 2] + getSum(i, up, down);
146             }
147         }
148     }
149 
150     //out();
151 
152     //printf(" O 2 \n");
153 
154     FLAG ^= 1; /// O 2
155     memset(g, ~0x3f, sizeof(g));
156     for(int i = 1; i <= m; i++) {
157         for(int up = 1; up < n - 1; up++) {
158             for(int down = up + 2; down <= n; down++) {
159                 g[i][up][down] = std::max(h[i - 1][up][down], g[i - 1][up][down]) + getSum(i, up, up) + getSum(i, down, down);
160             }
161         }
162     }
163 
164     //out();
165 
166     FLAG ^= 1; /// O 3
167     memset(g, ~0x3f, sizeof(g));
168     for(int i = 1; i <= m; i++) {
169         for(int up = 1; up < n - 1; up++) {
170             for(int down = up + 2; down <= n; down++) {
171                 g[i][up][down] = h[i - 1][up][down] + getSum(i, up, down);
172             }
173         }
174     }
175 
176     //out();
177 
178     /// get p : max of g
179     memset(p, ~0x3f, sizeof(p));
180     for(int i = 1; i <= m; i++) {
181         p[i] = p[i - 1];
182         for(int up = 1; up < n - 1; up++) {
183             for(int down = up + 2; down <= n; down++) {
184                 p[i] = std::max(p[i], g[i][up][down]);
185             }
186         }
187     }
188 
189     //outp();
190 
191     //out();
192 
193     FLAG ^= 1; /// I 1
194     memset(g, ~0x3f, sizeof(g));
195     for(int i = 5; i <= m; i++) {
196         for(int up = 1; up < n - 1; up++) {
197             for(int down = up + 2; down <= n; down++) {
198                 g[i][up][down] = std::max(p[i - 2], g[i - 1][up][down]) + getSum(i, up, up) + getSum(i, down, down);
199             }
200         }
201     }
202 
203     //out();
204 
205     FLAG ^= 1; /// I 2
206     memset(g, ~0x3f, sizeof(g));
207     for(int i = 1; i <= m; i++) {
208         for(int up = 1; up < n - 1; up++) {
209             for(int down = up + 2; down <= n; down++) {
210                 g[i][up][down] = std::max(g[i - 1][up][down], h[i - 1][up][down]) + getSum(i, up, down);
211             }
212         }
213     }
214 
215     //out();
216     int ans = -INF;
217 
218     FLAG ^= 1; /// I 3
219     memset(g, ~0x3f, sizeof(g));
220     for(int i = 1; i <= m; i++) {
221         for(int up = 1; up < n - 1; up++) {
222             for(int down = up + 2; down <= n; down++) {
223                 g[i][up][down] = std::max(g[i - 1][up][down], h[i - 1][up][down]) + getSum(i, up, up) + getSum(i, down, down);
224                 ans = std::max(g[i][up][down], ans);
225             }
226         }
227     }
228 
229     //out();
230 
231     printf("%d\n", ans);
232     return 0;
233 }
AC代碼
相關文章
相關標籤/搜索