1 一、背包
2 1.各种01背包
3 void leastOne_Pack(int id, int num ) {//至少取一个;
4 int i, j, c, v ;
5 for(i = 1 ; i <= num ; i ++ )
6 {
7 scanf("%d %d", &c, &v) ;
8 for(j = T ; j >= c ; j -- )
9 {// 下面的顺序不能交换;
10 if(f[id][j-c] != -1 ) f[id][j] = getMax(f[id][j], f[id][j-c] + v ) ;
11 if(f[id-1][j-c] != -1 ) f[id][j] = getMax(f[id][j], f[id-1][j-c] + v ) ;
12 }
13 }
14 }
15 void mostOne_Pack(int id, int num ) { // 最多取一个;
16 int i, j ;
17 int c[N], v[N] ;
18 for(i = 1 ; i <= num ; i ++ ) scanf("%d %d", &c[i], &v[i] ) ;
19 for(i = 0 ; i <= T ; i ++ ) f[id][i] = f[id-1][i] ;
20 for(i = 1 ; i <= num ; i ++ )
21 {
22 for(j = T ; j >= c[i] ; j --)
23 if(j >= c[i] && f[id-1][j-c[i]] != -1 ) f[id][j] = getMax(f[id][j], f[id-1][j-c[i]] + v[i] ) ;
24 }
25 }
26 void common_Pack(int id, int num ){ // 一般的01背包;
27 int i, j, c, v ;
28 for(i = 0 ; i <= T ; i ++ ) f[id][i] = f[id-1][i] ;
29 for(i = 1 ; i <= num ; i ++ )
30 {
31 scanf("%d %d", &c, &v) ;
32 for(j = T ; j >= c ; j -- )
33 if(f[id][j-c] != -1 ) f[id][j] = getMax(f[id][j], f[id][j-c] + v ) ;
34 }
35 }
36 2.完全背包
37 void Comlepte_Pack(){
38 for(i = 0 ; i < n ; i ++ )
39 {
40 scanf("%d %d", &p, &w ) ;
41 for(j = w ; j <= vol ; j ++ )
42 f[j] = f[j] < f[j-w] + p ? f[j] : f[j-w] + p ;
43 }
44 }
45 3.依赖背包
46 struct Goods{
47 int c, v ;
48 } g[61][61] ;
49 void dependent_Pack(int vol, int gn ){
50 int i, j, k, mc, mv, c, v ;
51 for(j = 1, f[0] = 0 ; j <= vol ; j ++ ) f[j] = -1 ;
52 for(i = 1 ; i <= gn ; i ++ )
53 {
54 if( !num[i]) continue ;
55 mc = g[i][0].c ; mv = g[i][0].v*mc ;
56 for(j = 1, h[0] = 0 ; j <= vol-mc ; j++ ) h[j] = -1 ;
57 for(k = 1 ; k < num[i] ; k ++ )//10背包,相当于得到0 - vol-mc种物品;
58 {
59 c = g[i][k].c ; v = g[i][k].v*c ;
60 for(j = vol-mc ; j >= c ; j -- )
61 if(h[j-c] != -1 ) h[j] = h[j] > h[j-c]+v ? h[j] : h[j-c]+v ;
62 }
63 for(j = vol ; j >= mc ; j -- )//对于1 - vol-mc种物品,至多选择一种;
64 {
65 for(k = 0 ; k <= j-mc ; k ++ )
66 {
67 if(h[k] == -1 ) continue ;
68 c = k+mc ; v = h[k]+mv ;
69 if(j >= c && f[j-c] != -1 ) f[j] = f[j] > f[j-c]+v ? f[j] : f[j-c]+v ;
70 }
71 }
72 }
73 }
74 二、极大化
75 1.极大化算法一
76 以障碍点经过的边作为矩形的左边界,一直向右边扫描
77 struct Point{
78 int x, y ;
79 }p[MAXN] ;
80 bool comp(Point a, Point b){
81 if(a.x == b.x) return a.y < b.y ;
82 else return a.x < b.x ;
83 }
84 int DP(){// h,d 表示扫描线的上下端点高度
85 int i, j, h, d, s ;
86 int ans = 0 ;
87 for (i = 1; i <= n; i ++) //枚举障碍点
88 {
89 h = W ; d = 0 ;
90 for(j = i+1 ; j <= n && h > d ; j ++)
91 {
92 if(p[i].x == p[j].x || p[j].y > h || p[j].y < d) continue ;
93 // 扫描得到的矩形一定要经过i点
94 s = (h-d)*(p[j].x-p[i].x) ;
95 ans = ans > s ? ans : s ;
96 if(p[j].y < h && p[j].y >= p[i].y) h = p[j].y ;
97 //保证向前扫描一定经过i点
98 if(p[j].y > d && p[j].y <= p[i].y) d = p[j].y ;
99 }
100 }
101 return ans ;
102 }
103 int solve(){
104 int i, j, tx, ans = 0 ;
105 while(~scanf("%d %d", &L, &W))
106 {
107 scanf("%d", &n) ; memset(pre, 0, sizeof(pre)) ;
108 for(i = 1 ; i <= n ; i ++)
109 {
110 scanf("%d %d", &p[i].x, &p[i].y) ; pre[p[i].y] = 1 ;
111 }
112 for(tx = 0, i = 1 ; i <= W ; i ++)
113 {
114 tx ++ ;
115 if(pre[i])
116 {
117 ans = ans > tx ? ans : tx ;
118 tx = 0 ;
119 }
120 }
121 ans = ans*L ;
122 p[++n].x = 0 ; p[n].y = 0 ; p[++n].x = 0 ; p[n].y = W ;
123 p[++n].x = L ; p[n].y = 0 ; p[++n].x = L ; p[n].y = W ;
124 sort(p+1, p+1+n, comp) ;
125 tx = DP() ; printf("%d\n", ans > tx ? ans : tx) ;
126 }
127 }
128
129
130
131
132
133 2.算法二
134 a.悬线的定义:上端点是障碍点或者边界的线段 ;
135 (1) h[i][j]表示以点(i,j)结束的悬线的最大长度;
136 (2) l[i][j]表示悬线(i,j)左移量,r[i][j]表示其右移量;
137 (3) ml[i][j]表示点(i,j)左边最近的障碍点位置,没有时为左边界。同理……
138 b.dp方程:
139 (1) 如果点(i-1,j)为障碍点或边界(i=0):
140 h[i][j] = 1,l[i][j] = L(大矩形长度),r[i][j] = 0;
141 (2) 如果点(i-1,j)不为障碍点:
142 h[i][j]=h[i-1][j]+1,
143 l[i][j]=max(l[i-1][j],ml[i][j]),
144 r[i][j]=min(r[i-1][j],mr[i][j]).
145 description :取最大周长矩形,该矩形要么由一种颜色覆盖,要么由两种颜色交叉覆盖。
146 int h[3][MAXN][MAXN], l[3][MAXN][MAXN], r[3][MAXN][MAXN] ;
147 int mr[3][MAXN][MAXN], ml[3][MAXN][MAXN] ;
148 //[i][j] 左右边最近的异色点,没有异色点为边界位置
149 int map[MAXN][MAXN] ;
150 void getTable(){//初始化数组
151 int i, j ;
152 for(i = 1 ; i <= n ; i ++)
153 {
154 map[i][0] = map[i][1] ; map[i][m+1] = map[i][m] ;
155 ml[0][i][0] = 0 ; mr[0][i][m+1] = m+1 ;
156 for(j = 1 ; j <= m ; j ++)
157 {
158 ml[1][i][j] = ml[0][i][j] =
159 (map[i][j]==map[i][j-1]) ? ml[0][i][j-1] : j-1 ;
160 ml[2][i][j] =
161 (map[i][j]^map[i][j-1]) ? ml[2][i][j-1] : j-1 ;
162 }
163 for(j = m ; j ; j --)
164 {
165 mr[1][i][j] = mr[0][i][j] =
166 (map[i][j]==map[i][j+1]) ? mr[0][i][j+1] : j+1 ;
167 mr[2][i][j] =
168 (map[i][j]^map[i][j+1]) ? mr[2][i][j+1] : j+1 ;
169 }
170 }
171 }
172 int DP(){
173 int i, j, k, ans = 0 ;
174 for (i = 1 ; i <= n ; i ++)
175 for (j = 1 ; j <= m ; j ++)
176 {
177 for(k = 0 ; k < 3 ; k ++)
178 {
179 if(k < 2 && (map[i][j] != k)) continue ;
180 bool v = map[i][j]^map[i-1][j] ;
181 if(i == 1 || ((2-k) && v) || (!(2-k) && !v) ) //特判
182 {
183 h[k][i][j] = 1 ;
184 l[k][i][j] = ml[k][i][j] ;
185 r[k][i][j] = mr[k][i][j] ;
186 }
187 else {
188 h[k][i][j] = h[k][i-1][j]+1 ;
189 l[k][i][j] = max(l[k][i-1][j], ml[k][i][j]) ;
190 r[k][i][j] = min(r[k][i-1][j], mr[k][i][j]) ;
191 }
192 ans = max(ans, 2*(r[k][i][j]-l[k][i][j]-1+h[k][i][j])) ;
193 }
194 }
195 return ans ;
196 }
197 int solve(){
198 getTable() ; printf("Case #%d: %d\n", cas ++, DP()) ;
199 }
200 三、分数规划
201 1.二分法
202 double DP(double f){
203 int i ;
204 double ans ;
205 for(i = 1 ; i <= n ; i ++) d[i] = 1.0*a[i] - b[i]*f;
206 sum[0] = 0.0 ;
207 for(i = 1 ; i <= n ; i ++) sum[i] = sum[i-1] + d[i] ;
208 ans = sum[k] ; dp[k] = sum[k] ;
209 for(i = k+1 ; i <= n ; i ++)
210 {
211 dp[i] = max(sum[i]-sum[i-k], dp[i-1]+d[i]) ;
212 ans = max(ans, dp[i]) ;
213 }
214 return ans ;
215 }
216 double binary(double l, double r){
217 double mid ;
218 while(r-l > EPS)
219 {
220 mid = (l+r)/2.0 ;
221 if(DP(mid) > EPS) l = mid+EPS ;
222 else r = mid ;
223 }
224 return l ;
225 }
226 2.牛顿逼近法
227 void build(double s){
228 int i, j ;
229 for(i = 1 ; i <= n ; i ++)
230 for(j = 1 ; j <= n ; j ++)
231 {
232 map[i][j].d = map[i][j].l - s*map[i][j].c ;
233 }
234 }
235 double solve(){
236 int i ;
237 double s, ans = 1.0 ;
238 do {
239 s = ans ;
240 build(s) ;
241 ans = kruskal(1) ;
242 }while(fabs(ans-s) > EPS) ;
243 return 1.0/ans ;
244 }
245 四、经典模型
246 1.LICS平方算法
247 int dp[MAXN][MAXN] ; // dp[i][j]表示a[1-i]到b[1-j]且以b[j]结尾的LCIS ;
248 int dp_LCIS(){
249 int i, j, max_l , ans = 0 ;
250 for(i = 1 ; i <= m ; i ++) dp[0][i] = 0 ;
251 for(i = 1 ; i <= n ; i ++)
252 {
253 max_l = 0 ;
254 for(j = 1 ; j <= m ; j ++)
255 {
256 dp[i][j] = dp[i-1][j] ;
257 if(a[i] > b[j]) max_l = max(max_l, dp[i-1][j]) ;
258 //因为相当于a[i] > b[k]与b[j] > b[k]等价( >= 是非递减);
259 if(a[i] == b[j]) dp[i][j] = max_l + 1 ;
260 }
261 ans = max(ans, dp[i][m]) ;
262 }
263 return ans ;
264 }
265 2.最长回文序列
266 int solve(){ //最长回文子序列
267 int i, j, tmp ;
268 memset(dp, 0, sizeof(dp)) ;
269 for(i = 1 ; i <= 3*n ; i ++) dp[i][i] = 1 ;
270 for(i = 3*n-1 ; i ; i --)
271 {
272 for(j = i+1 ; j <= 3*n ; j ++)
273 {
274 dp[i][j] = max(dp[i+1][j], dp[i][j-1]) ;
275 tmp = dp[i+1][j-1] + 2*(ar[i] == ar[j]) ;
276 dp[i][j] = max(dp[i][j], tmp) ;
277 }
278 }
279 int ans = 1 ;
280 for(i = n+1 ; i <= 2*n ; i ++) ans = max(ans, dp[i-n+1][i+n-1]) ;
281 return ans ;
282 }
283 3.最短编辑距离
284 int solve(){//最短编辑距离
285 int i, j, tmp, mx = max(ls, lt) ;
286 for(i = 0 ; i <= ls ; i ++)
287 for(j = 0 ; j <= lt ; j ++) dp[i][j] = mx ;
288 for(i = 0 ; i <= mx ; i ++) dp[i][0] = dp[0][i] = i ;
289 for(i = 1 ; i <= ls ; i ++ )
290 {
291 for(j = 1 ; j <= lt ; j ++)
292 {
293 tmp = min(dp[i-1][j]+1, dp[i][j-1]+1) ;
294 if(s[i] == t[j]) dp[i][j] = min(dp[i][j], min(dp[i-1][j-1], tmp )) ;
295 else dp[i][j] = min(dp[i][j], min(tmp, dp[i-1][j-1] + 1)) ;
296 }
297 }
298 for(i = 1 ; i <= ls ; i ++) printf("%d ", dp[i][lt]) ; puts("") ;
299 return dp[ls][lt] ;
300 }
301 4.最长公共子序列个数
302 bool solve(){//最长公共子序列个数
303 int i, j ; bool d = 0 ;
304 memset(f[d], 0, sizeof(f[d])) ; memset(g[d], 0, sizeof(g[d])) ;
305 for(i = max(n, m) ; i >= 0 ; i --) g[d][i] = 1 ;
306 for(i = 1 ; i <= n ; i ++)
307 {
308 memset(f[!d], 0, sizeof(f[!d])) ; memset(g[!d], 0, sizeof(g[!d])) ;
309 g[!d][0] = 1 ;
310 for(j = 1 ; j <= m ; j ++)
311 {
312 if(s[i] == t[j])
313 {
314 f[!d][j] = f[d][j-1] + 1 ;
315 g[!d][j] = g[d][j-1] ;
316 if(f[!d][j] == f[d][j])
317 g[!d][j] = (g[!d][j] + g[d][j]) % MOD ;
318 if(f[!d][j] == f[!d][j-1])
319 g[!d][j] = (g[!d][j] + g[!d][j-1]) % MOD ;
320 }
321 else
322 {
323 f[!d][j] = max(f[d][j], f[!d][j-1]) ;
324 if(f[!d][j] == f[d][j])
325 g[!d][j] = (g[!d][j] + g[d][j]) % MOD ;
326 if(f[!d][j] == f[!d][j-1])
327 g[!d][j] = (g[!d][j] + g[!d][j-1]) % MOD ;
328 if(f[!d][j] == f[d][j-1])
329 g[!d][j] = ( g[!d][j] - g[d][j-1] + MOD) % MOD ;
330 }
331 }
332 d = !d ;
333 }
334 return d ;
335 }