学习笔记——悬线法

学呀学呀学呀学,学完了。ios

悬线法用来解决最大子矩阵问题。git

嗯,就是那种DP的题。编程

嗯,学完了,就这些。app

 

 

题目描述  Description

在一个0,1方阵中找出其中最大的全0子矩阵,所谓最大是指O的个数最多。ide

输入描述  Input Description

输入文件第一行为整数N,其中1<=N<=2000,为方阵的大小,紧接着N行每行均有N个0或1,相邻两数间严格用一个空格隔开。学习

输出描述  Output Description

输出文件仅一行包含一个整数表示要求的最大的全零子矩阵中零的个数。spa

样例输入  Sample Input

5
0 1 0 1 0
0 0 0 0 0
0 0 0 0 1
1 0 0 0 0
0 1 0 0 0code

样例输出  Sample Output

9blog

 

#include<iostream> #include<cstdio> #include<algorithm> #include<cstring>
using namespace std; const int N=2e3+5; int n,ans; int map[N]; int h[N],l[N],r[N]; inline int read() { char c=getchar();int num=0; for(;!isdigit(c);c=getchar()) if(c=='F') return 0; else if(c=='R') return 1; for(;isdigit(c);c=getchar()) num=num*10+c-'0'; return num; } int main() { n=read(); for(int i=1;i<=n;++i) l[i]=0,r[i]=n; for(int i=1,tmp;i<=n;++i) { tmp=1; for(int j=1;j<=n;++j) { map[j]=read(); h[j]=map[j]==0?h[j]+1:0; tmp=map[j]?j+1:tmp; l[j]=map[j]==0?max(l[j],tmp):1; } tmp=n; for(int j=n;j;--j) { tmp=map[j]?j-1:tmp; r[j]=map[j]==0?min(r[j],tmp):n; ans=max(ans,(r[j]-l[j]+1)*h[j]); } } printf("%d",ans); return 0; }
View Code

 

 

P4147 玉蟾宫

题目背景

有一天,小猫rainbow和freda来到了湘西张家界的天门山玉蟾宫,玉蟾宫宫主蓝兔盛情地款待了它们,并赐予它们一片土地。ip

题目描述

这片土地被分红N*M个格子,每一个格子里写着'R'或者'F',R表明这块土地被赐予了rainbow,F表明这块土地被赐予了freda。

如今freda要在这里卖萌。。。它要找一块矩形土地,要求这片土地都标着'F'而且面积最大。

可是rainbow和freda的OI水平都弱爆了,找不出这块土地,而蓝兔也想看freda卖萌(她显然是不会编程的……),因此它们决定,若是你找到的土地面积为S,它们每人给你S两银子。

输入输出格式

输入格式:

 

第一行两个整数N,M,表示矩形土地有N行M列。

接下来N行,每行M个用空格隔开的字符'F'或'R',描述了矩形土地。

 

输出格式:

 

输出一个整数,表示你能获得多少银子,即(3*最大'F'矩形土地面积)的值。

 

输入输出样例

输入样例#1:  复制
5 6 
R F F F F F 
F F F F F F 
R R R F F F 
F F F F F F 
F F F F F F
输出样例#1:  复制
45

说明

对于50%的数据,1<=N,M<=200

对于100%的数据,1<=N,M<=1000

 

#include<iostream> #include<cstdio> #include<algorithm> #include<cstring>
using namespace std; const int N=2e3+5; int n,m,ans; int map[N]; int h[N],l[N],r[N]; inline int read() { char c=getchar();int num=0; for(;!isdigit(c);c=getchar()) if(c=='F') return 0; else if(c=='R') return 1; for(;isdigit(c);c=getchar()) num=num*10+c-'0'; return num; } int main() { n=read(),m=read(); for(int i=1;i<=m;++i) l[i]=0,r[i]=m; for(int i=1,tmp;i<=n;++i) { tmp=1; for(int j=1;j<=m;++j) { map[j]=read(); h[j]=map[j]==0?h[j]+1:0; tmp=map[j]?j+1:tmp; l[j]=map[j]==0?max(l[j],tmp):1; } tmp=m; for(int j=m;j;--j) { tmp=map[j]?j-1:tmp; r[j]=map[j]==0?min(r[j],tmp):m; ans=max(ans,(r[j]-l[j]+1)*h[j]); } } printf("%d",ans*3); return 0; }
View Code

 

 

P1578 奶牛浴场

题目描述

因为John建造了牛场围栏,激起了奶牛的愤怒,奶牛的产奶量急剧减小。为了讨好奶牛,John决定在牛场中建造一个大型浴场。可是John的奶牛有一个奇怪的习惯,每头奶牛都必须在牛场中的一个固定的位置产奶,而奶牛显然不能在浴场中产奶,因而,John但愿所建造的浴场不覆盖这些产奶点。这回,他又要求助于Clevow了。你还能帮助Clevow吗?

John的牛场和规划的浴场都是矩形。浴场要彻底位于牛场以内,而且浴场的轮廓要与牛场的轮廓平行或者重合。浴场不能覆盖任何产奶点,可是产奶点能够位于浴场的轮廓上。

Clevow固然但愿浴场的面积尽量大了,因此你的任务就是帮她计算浴场的最大面积。

输入输出格式

输入格式:

 

输入文件的第一行包含两个整数L和W,分别表示牛场的长和宽。文件的第二行包含一个整数n,表示产奶点的数量。如下n行每行包含两个整数x和y,表示一个产奶点的坐标。全部产奶点都位于牛场内,即:0<=x<=L,0<=y<=W。

 

输出格式:

 

输出文件仅一行,包含一个整数S,表示浴场的最大面积。

 

输入输出样例

输入样例#1:  复制
10 10
4
1 1
9 1
1 9
9 9
输出样例#1:  复制
80

说明

0<=n<=5000

1<=L,W<=30000

Winter Camp 2002

 

//悬线法学习练习 //并不是悬线法的作法 //悬线法pre //复杂度 O(障碍数的个数^2) //仍是挺优秀的 
 #include<iostream> #include<cstdio> #include<cstring> #include<cmath> #include<algorithm>
using namespace std; const int N=3e4+5; int n,m,s; int ans; struct OBS { int x,y; }obs[N]; inline int read() { char c=getchar();int num=0; for(;!isdigit(c);c=getchar()); for(;isdigit(c);c=getchar()) num=num*10+c-'0'; return num; } bool cmp1(const OBS &a,const OBS &b) { return a.y<b.y; } bool cmp2(const OBS &a,const OBS &b) { return a.x<b.x; } int main() { n=read(),m=read(); s=read(); for(int i=1;i<=s;++i) obs[i].x=read(),obs[i].y=read(); obs[++s].x=0,obs[s].y=0; obs[++s].x=n,obs[s].y=0; obs[++s].x=0,obs[s].y=m; obs[++s].x=n,obs[s].y=m; sort(obs+1,obs+s+1,cmp1); for(int i=1,L,H,cei,flo,len;i<=s;++i) { H=obs[i].x,L=obs[i].y,len=m-L; cei=0,flo=n; for(int j=i+1;j<=s;++j) { if(len*(flo-cei)<=ans) break; if(obs[j].x<cei||obs[j].x>flo) continue; ans=max(ans,(obs[j].y-L)*(flo-cei)); if(obs[j].x==H) break; else if(obs[j].x<H) cei=obs[j].x; else flo=obs[j].x; } } for(int i=m,R,H,cei,flo,len;i;--i) { H=obs[i].x,R=obs[i].y,len=R; cei=0,flo=n; for(int j=i-1;j;--j) { if(len*(flo-cei)<=ans) break; if(obs[j].x<cei||obs[j].x>flo) continue; ans=max(ans,(R-obs[j].y)*(flo-cei)); if(obs[j].x==H) break; else if(obs[j].x<H) cei=obs[j].x; else flo=obs[j].x; } } sort(obs+1,obs+s+1,cmp2); for(int i=1;i<s;++i) { // printf("%d %d\n",obs[i+1].x,obs[i].x);
        ans=max(ans,(obs[i+1].x-obs[i].x)*m); } printf("%d",ans); return 0; }
不是悬线法 悬线法pre
相关文章
相关标签/搜索