zoukankan      html  css  js  c++  java
  • 学习笔记——悬线法

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

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

    嗯,就是那种DP的题。

    嗯,学完了,就这些。

    题目描述 Description

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

    输入描述 Input Description

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

    输出描述 Output Description

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

    样例输入 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 0

    样例输出 Sample Output

    9

    #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来到了湘西张家界的天门山玉蟾宫,玉蟾宫宫主蓝兔盛情地款待了它们,并赐予它们一片土地。

    题目描述

    这片土地被分成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
    ",obs[i+1].x,obs[i].x);
            ans=max(ans,(obs[i+1].x-obs[i].x)*m);
        }
        printf("%d",ans);
        return 0;
    }
    不是悬线法 悬线法pre
  • 相关阅读:
    Oracle通过透明网关连接SQL SERVER
    无法初始化链接服务器 "(null)" 的 OLE DB 访问接口 "Microsoft.Jet.OLEDB.4.0" 的数据源
    DBGrid应用
    C#学习之C#3.0语言功能
    windows 下 java 环境配置
    discuz UCenter对接遇到问题总汇
    mysql 备份之mysqldump 常用命令
    struts2与FreeMarker 简单配置实现
    hessian 简单实现
    jquery ui
  • 原文地址:https://www.cnblogs.com/lovewhy/p/8972080.html
Copyright © 2011-2022 走看看