悬线法刷题记录

最近学习了悬线法,用极大化思想解决最大子矩阵问题,一种dp问题,留个记录……

讲的特别好的一个博客:极大化思想解决最大子矩阵问题

例题:

P1169 [ZJOI2007]棋盘制作

代码如下:

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <algorithm>
 4 #include <cstring>
 5 #include <vector>
 6 #define rep(x, l, r) for(int x = l; x <= r; x++)
 7 #define repd(x, r, l) for(int x = r; x >= l; x--)
 8 #define clr(x, y) memset(x, y, sizeof(x))
 9 #define all(x) x.begin(), x.end()
10 #define pb push_back
11 #define mp make_pair
12 #define MAXN 2005
13 #define fi first
14 #define se second
15 #define SZ(x) ((int)x.size())
16 using namespace std;
17 typedef long long ll;
18 typedef vector<int> vi;
19 typedef pair<int, int> pii;
20 const int INF = 1 << 30;
21 const int p = 1000000009;
22 int lowbit(int x){ return x & (-x);}
23 int fast_power(int a, int b){ int x; for(x = 1; b; b >>= 1){ if(b & 1) x = 1ll * x * a % p; a = 1ll * a * a % p;} return x % p;}
24
25 int a[MAXN][MAXN], l[MAXN][MAXN], r[MAXN][MAXN], height[MAXN][MAXN];
26
27 int main(){
28     int n, m;
29     scanf("%d%d", &n, &m);
30     rep(i, 1, n)
31         rep(j, 1, m){
32             scanf("%d", &a[i][j]);
33             height[i][j] = 1;
34             l[i][j] = r[i][j] = j;
35         }
36     rep(i, 1, n){
37         rep(j, 2, m)
38             if(a[i][j] != a[i][j - 1]) l[i][j] = l[i][j - 1];
39     }
40     rep(i, 1, n){
41         repd(j, m - 1, 1)
42             if(a[i][j] != a[i][j + 1]) r[i][j] = r[i][j + 1];
43     }
44     int ans1 = 0, ans2 = 0;
45     rep(i, 1, n){
46         rep(j, 1, m){
47             if(i != 1 && a[i - 1][j] != a[i][j]){
48                 height[i][j] = height[i - 1][j] + 1;
49                 l[i][j] = max(l[i][j], l[i - 1][j]);
50                 r[i][j] = min(r[i][j], r[i - 1][j]);
51             }
52             ans1 = max(ans1, min(height[i][j], r[i][j] - l[i][j] + 1) * min(height[i][j], r[i][j] - l[i][j] + 1));
53             ans2 = max(ans2, height[i][j] * (r[i][j] - l[i][j] + 1));
54         }
55     }
56     printf("%d\n%d\n", ans1, ans2);
57     return 0;
58 }

P4147 玉蟾宫

代码如下:

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <algorithm>
 4 #include <cstring>
 5 #include <vector>
 6 #define rep(x, l, r) for(int x = l; x <= r; x++)
 7 #define repd(x, r, l) for(int x = r; x >= l; x--)
 8 #define clr(x, y) memset(x, y, sizeof(x))
 9 #define all(x) x.begin(), x.end()
10 #define pb push_back
11 #define mp make_pair
12 #define MAXN 1005
13 #define fi first
14 #define se second
15 #define SZ(x) ((int)x.size())
16 using namespace std;
17 typedef long long ll;
18 typedef vector<int> vi;
19 typedef pair<int, int> pii;
20 const int INF = 1 << 30;
21 const int p = 1000000009;
22 int lowbit(int x){ return x & (-x);}
23 int fast_power(int a, int b){ int x; for(x = 1; b; b >>= 1){ if(b & 1) x = 1ll * x * a % p; a = 1ll * a * a % p;} return x % p;}
24
25 int n, m;
26 int a[MAXN][MAXN], l[MAXN][MAXN], r[MAXN][MAXN], height[MAXN][MAXN];
27
28 int main(){
29     scanf("%d%d", &n, &m);
30     rep(i, 1, n)
31         rep(j, 1, m){
32             char ch[5];
33             scanf("%s", ch);
34             a[i][j] = ch[0] == ‘F‘;
35             l[i][j] = r[i][j] = j;
36             height[i][j] = 1;
37         }
38     rep(i, 1, n)
39         rep(j, 2, m)
40             if(a[i][j] && a[i][j - 1]) l[i][j] = l[i][j - 1];
41     rep(i, 1, n)
42         repd(j, m - 1, 1)
43             if(a[i][j] && a[i][j + 1]) r[i][j] = r[i][j + 1];
44     int ans = 0;
45     rep(i, 1, n)
46         rep(j, 1, m){
47             if(!a[i][j]) continue;
48             if(i != 1 && a[i - 1][j]){
49                 l[i][j] = max(l[i][j], l[i - 1][j]);
50                 r[i][j] = min(r[i][j], r[i - 1][j]);
51                 height[i][j] = height[i - 1][j] + 1;
52             }
53             ans = max(ans, height[i][j] * (r[i][j] - l[i][j] + 1));
54         }
55     printf("%d\n", 3 * ans);
56     return 0;
57 }

P2701 [USACO5.3]巨大的牛棚Big Barn

代码如下:

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <algorithm>
 4 #include <cstring>
 5 #include <vector>
 6 #define rep(x, l, r) for(int x = l; x <= r; x++)
 7 #define repd(x, r, l) for(int x = r; x >= l; x--)
 8 #define clr(x, y) memset(x, y, sizeof(x))
 9 #define all(x) x.begin(), x.end()
10 #define pb push_back
11 #define mp make_pair
12 #define MAXN 1005
13 #define fi first
14 #define se second
15 #define SZ(x) ((int)x.size())
16 using namespace std;
17 typedef long long ll;
18 typedef vector<int> vi;
19 typedef pair<int, int> pii;
20 const int INF = 1 << 30;
21 const int p = 1000000009;
22 int lowbit(int x){ return x & (-x);}
23 int fast_power(int a, int b){ int x; for(x = 1; b; b >>= 1){ if(b & 1) x = 1ll * x * a % p; a = 1ll * a * a % p;} return x % p;}
24
25 int a[MAXN][MAXN], l[MAXN][MAXN], r[MAXN][MAXN], height[MAXN][MAXN];
26
27 int main(){
28     int n, m;
29     scanf("%d%d", &n, &m);
30     rep(i, 1, m){
31         int x, y;
32         scanf("%d%d", &x, &y);
33         a[x][y] = 1;
34     }
35     rep(i, 1, n)
36         rep(j, 1, n){
37             l[i][j] = r[i][j] = j;
38             height[i][j] = 1;
39         }
40     rep(i, 1, n)
41         rep(j, 2, n)
42             if(!a[i][j - 1] && !a[i][j]) l[i][j] = l[i][j - 1];
43     rep(i, 1, n)
44         repd(j, n - 1, 1)
45             if(!a[i][j + 1] && !a[i][j]) r[i][j] = r[i][j + 1];
46     int ans = 0;
47     rep(i, 1, n)
48         rep(j, 1, n){
49             if(a[i][j]) continue;
50             if(i != 1 && !a[i - 1][j]){
51                 height[i][j] = height[i - 1][j] + 1;
52                 l[i][j] = max(l[i][j], l[i - 1][j]);
53                 r[i][j] = min(r[i][j], r[i - 1][j]);
54             }
55             ans = max(ans, min(height[i][j], r[i][j] - l[i][j] + 1));
56         }
57     printf("%d\n", ans);
58     return 0;
59 }

P1387 最大正方形

代码如下

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <algorithm>
 4 #include <cstring>
 5 #include <vector>
 6 #define rep(x, l, r) for(int x = l; x <= r; x++)
 7 #define repd(x, r, l) for(int x = r; x >= l; x--)
 8 #define clr(x, y) memset(x, y, sizeof(x))
 9 #define all(x) x.begin(), x.end()
10 #define pb push_back
11 #define mp make_pair
12 #define MAXN 1005
13 #define fi first
14 #define se second
15 #define SZ(x) ((int)x.size())
16 using namespace std;
17 typedef long long ll;
18 typedef vector<int> vi;
19 typedef pair<int, int> pii;
20 const int INF = 1 << 30;
21 const int p = 1000000009;
22 int lowbit(int x){ return x & (-x);}
23 int fast_power(int a, int b){ int x; for(x = 1; b; b >>= 1){ if(b & 1) x = 1ll * x * a % p; a = 1ll * a * a % p;} return x % p;}
24
25 int a[MAXN][MAXN], l[MAXN][MAXN], r[MAXN][MAXN], height[MAXN][MAXN];
26
27 int main(){
28     int n, m;
29     scanf("%d%d", &n, &m);
30     rep(i, 1, n)
31         rep(j, 1, m){
32             scanf("%d", &a[i][j]);
33             l[i][j] = r[i][j] = j;
34             height[i][j] = 1;
35         }
36     rep(i, 1, n)
37         rep(j, 2, m)
38             if(a[i][j - 1] && a[i][j]) l[i][j] = l[i][j - 1];
39     rep(i, 1, n)
40         repd(j, m - 1, 1)
41             if(a[i][j + 1] && a[i][j]) r[i][j] = r[i][j + 1];
42     int ans = 0;
43     rep(i, 1, n)
44         rep(j, 1, m){
45             if(!a[i][j]) continue;
46             if(i != 1 && a[i - 1][j]){
47                 height[i][j] = height[i - 1][j] + 1;
48                 l[i][j] = max(l[i][j], l[i - 1][j]);
49                 r[i][j] = min(r[i][j], r[i - 1][j]);
50             }
51             ans = max(ans, min(height[i][j], r[i][j] - l[i][j] + 1));
52         }
53     printf("%d\n", ans);
54     return 0;
55 }

原文地址:https://www.cnblogs.com/nblyz2003/p/12174450.html

时间: 2024-10-08 03:36:22

悬线法刷题记录的相关文章

Codevs 1159 最大全0子矩阵 悬线法!!!!

1159 最大全0子矩阵 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 黄金 Gold 题目描述 Description 在一个0,1方阵中找出其中最大的全0子矩阵,所谓最大是指O的个数最多. 输入描述 Input Description 输入文件第一行为整数N,其中1<=N<=2000,为方阵的大小,紧接着N行每行均有N个0或1,相邻两数间严格用一个空格隔开. 输出描述 Output Description 输出文件仅一行包含一个整数表示要求的最大的全零子矩阵中零的个数.

[codevs1159]最大全0子矩阵(悬线法)

解题关键:悬线法模板题.注意此模板用到了滚动数组. #include<cstdio> #include<cstring> #include<algorithm> #include<cstdlib> #include<iostream> #include<cmath> #define maxn 2002 using namespace std; typedef long long ll; int map[maxn][maxn],l[ma

【BZOJ-3039&amp;1057】玉蟾宫&amp;棋盘制作 悬线法

3039: 玉蟾宫 Time Limit: 2 Sec  Memory Limit: 128 MBSubmit: 753  Solved: 444[Submit][Status][Discuss] Description 有一天,小猫rainbow和freda来到了湘西张家界的天门山玉蟾宫,玉蟾宫宫主蓝兔盛情地款待了它们,并赐予它们一片土地.这片土地被分成N*M个格子,每个格子里写着'R'或者'F',R代表这块土地被赐予了rainbow,F代表这块土地被赐予了freda.现在freda要在这里卖

重(zhong)新学习悬线法

2017.9.28今天模拟赛T1就是求最大子矩阵的经典题 然而我已经好久没有写悬线了,以前悬线也是拉的,于是现在就系统的学习一波吧 给定一个N * M的01矩阵,求最大全0矩阵的大小 N^3的做法其实有很多种,前缀和乱搞什么的都可以 考虑N^2的做法 对于任意一个非1的点i,j,记其向上能到达的最长长度为up[i][j] 显然up[i][j] = up[i-1][j] + 1 (a[i][j] == 0) up[i][j] = 0 (a[i][j] = 1)我们称up[i][j]为一条悬线 显然

【bzoj3039】玉蟾宫 悬线法

悬线法是一种更优秀的枚举方式,保证了枚举悬线的集合包含了极大子矩形所在的集合,而且由最大子矩形一定是极大子矩形的定理可知,这种枚举方式可以求出最大子矩形. 具体做法是维护矩形中每个元素对应最近的左边和右边的障碍点,再维护一个高度数组记录下每个点向上可以延伸多高,还有对应的矩形向左向右可以到达的最大宽度. 代码如下 #include <bits/stdc++.h> using namespace std; const int maxn=1e3+10; int n,m,a[maxn][maxn];

悬线法——有套路的DP

例题 P1169 [ZJOI2007]棋盘制作 题目描述 国际象棋是世界上最古老的博弈游戏之一,和中国的围棋.象棋以及日本的将棋同享盛名.据说国际象棋起源于易经的思想,棋盘是一个8×88 \times 88×8大小的黑白相间的方阵,对应八八六十四卦,黑白对应阴阳. 而我们的主人公小Q,正是国际象棋的狂热爱好者.作为一个顶尖高手,他已不满足于普通的棋盘与规则,于是他跟他的好朋友小W决定将棋盘扩大以适应他们的新规则. 小Q找到了一张由N×MN \times MN×M个正方形的格子组成的矩形纸片,每个

BZOJ 刷题记录 PART 4

[BZOJ1143]CTSC的题目...先用floyed传递闭包,然后直接上匈牙利算法. [BZOJ1452]从未写过的二维树状数组.好像很简单.. struct two_bit { int f[305][305]; inline void add(int x,int z,int A) { for (;x<=n;x+=L(x)) for (int y=z;y<=m;y+=L(y)) f[x][y]+=A; } inline int ask(int x,int z) { int ans=0; f

BZOJ 3039 玉蟾宫 悬线法

题目大意:给出一张地图,求出这张地图中最大的子矩阵,使得这个子矩阵不包含字母'R'. 思路:简单的悬线法求最大子矩阵,还是不带权值的,很好求.好久没写悬线了,复习一下. CODE: #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #define MAX 1010 using namespace std; int m,n; bool map[MAX][M

BZOJ 1057: [ZJOI2007]棋盘制作 悬线法求最大子矩阵+dp

1057: [ZJOI2007]棋盘制作 Description 国际象棋是世界上最古老的博弈游戏之一,和中国的围棋.象棋以及日本的将棋同享盛名.据说国际象棋起源于易经的思想,棋盘是一个8*8大小的黑白相间的方阵,对应八八六十四卦,黑白对应阴阳.而我们的主人公小Q,正是国际象棋的狂热爱好者.作为一个顶尖高手,他已不满足于普通的棋盘与规则,于是他跟他的好朋友小W决定将棋盘扩大以适应他们的新规则.小Q找到了一张由N*M个正方形的格子组成的矩形纸片,每个格子被涂有黑白两种颜色之一.小Q想在这种纸中裁减