學呀學呀學呀學,學完了。ios
懸線法用來解決最大子矩陣問題。git
嗯,就是那種DP的題。編程
嗯,學完了,就這些。app
在一個0,1方陣中找出其中最大的全0子矩陣,所謂最大是指O的個數最多。ide
輸入文件第一行爲整數N,其中1<=N<=2000,爲方陣的大小,緊接着N行每行均有N個0或1,相鄰兩數間嚴格用一個空格隔開。學習
輸出文件僅一行包含一個整數表示要求的最大的全零子矩陣中零的個數。spa
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
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; }
有一天,小貓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'矩形土地面積)的值。
對於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; }
因爲John建造了牛場圍欄,激起了奶牛的憤怒,奶牛的產奶量急劇減小。爲了討好奶牛,John決定在牛場中建造一個大型浴場。可是John的奶牛有一個奇怪的習慣,每頭奶牛都必須在牛場中的一個固定的位置產奶,而奶牛顯然不能在浴場中產奶,因而,John但願所建造的浴場不覆蓋這些產奶點。這回,他又要求助於Clevow了。你還能幫助Clevow嗎?
John的牛場和規劃的浴場都是矩形。浴場要徹底位於牛場以內,而且浴場的輪廓要與牛場的輪廓平行或者重合。浴場不能覆蓋任何產奶點,可是產奶點能夠位於浴場的輪廓上。
Clevow固然但願浴場的面積儘量大了,因此你的任務就是幫她計算浴場的最大面積。
輸入格式:
輸入文件的第一行包含兩個整數L和W,分別表示牛場的長和寬。文件的第二行包含一個整數n,表示產奶點的數量。如下n行每行包含兩個整數x和y,表示一個產奶點的座標。全部產奶點都位於牛場內,即:0<=x<=L,0<=y<=W。
輸出格式:
輸出文件僅一行,包含一個整數S,表示浴場的最大面積。
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; }