zoukankan      html  css  js  c++  java
  • HDU 6107 Typesetting

    Problem Description
    Yellowstar is writing an article that contains N words and 1 picture, and the i-th word contains ai characters.
    The page width is fixed to W characters. In order to make the article look more beautiful, Yellowstar has made some rules:

    1. The fixed width of the picture is pw. The distance from the left side of the page to the left side of the photo fixed to dw, in other words, the left margin is dw, and the right margin is W - pw - dw.
    2. The photo and words can't overlap, but can exist in same line.
    3. The relative order of words cannot be changed.
    4. Individual words need to be placed in a line.
    5. If two words are placed in a continuous position on the same line, then there is a space between them.
    6. Minimize the number of rows occupied by the article according to the location and height of the image.
      However, Yellowstar has not yet determined the location of the picture and the height of the picture, he would like to try Q different locations and different heights to get the best look. Yellowstar tries too many times, he wants to quickly know the number of rows each time, so he asked for your help. It should be noted that when a row contains characters or pictures, the line was considered to be occupied.

    题目大意:
    有N个单词,每一个单词长度为(a_i),现在存在一页纸,宽度为W,和一张需要放进纸中的照片,照片的宽度为pw,距离纸的左边x,距离右边W-pw-x,有Q组询问,(x,y)表示照片从第x行开始,长度为y,求把单词和照片都放进纸中,需要占用多少行

    解题报告:
    用时:1h,1WA
    比较简单,直接预处理出:
    (f[i][j])表示在没有照片的行中,从第(i)个单词开始,占用(2^j)行可以放下的单词数
    (g[i][j])表示在有照片的行中,从第(i)个单词开始,占用(2^j)行可以放下的单词数
    我们可以先用二分处理出(f[i][0])(g[i][0])
    显然:
    (f[i][j]=f[i][j-1]+f[i+f[i][j-1]][j-1])
    (g[i][j]=g[i][j-1]+g[i+g[i][j-1]][j-1])
    最后再分照片前的部分,照片的部分,和照片后的三个部分处理即可

    #include <algorithm>
    #include <iostream>
    #include <cstdlib>
    #include <cstring>
    #include <cstdio>
    #include <cmath>
    #define RG register
    #define il inline
    #define iter iterator
    #define Max(a,b) ((a)>(b)?(a):(b))
    #define Min(a,b) ((a)<(b)?(a):(b))
    using namespace std;
    const int N=1e5+5;
    int n,m,W,pw,lw,rw,a[N],sum[N],f[N][20];
    int g[N][20],maxlen;
    int midit(int sta,int lim){
        if(sta>n || !lim)return 0;
        int l=sta,r=n,mid,ret=l-1;
        while(l<=r){
            mid=(l+r)>>1;
            if(sum[mid]-sum[sta-1]+mid-sta<=lim)
                ret=mid,l=mid+1;
            else r=mid-1;
        }
        return ret-sta+1;
    }
    void prework(){
        int x,y;
        for(int i=1;i<=n;i++){
            f[i][0]=midit(i,W);
            x=midit(i,lw);y=midit(i+x,rw);
            g[i][0]=x+y;
        }
        for(int j=1;j<=maxlen;j++){
            for(int i=1;i<=n;i++){
                if(i+f[i][j-1]<=n)
                    f[i][j]=f[i][j-1]+f[i+f[i][j-1]][j-1];
                else f[i][j]=N;
                if(i+g[i][j-1]<=n)
                    g[i][j]=g[i][j-1]+g[i+g[i][j-1]][j-1];
                else g[i][j]=N;
                if(i+f[i][j]-1>n)f[i][j]=N;
                if(i+g[i][j]-1>n)g[i][j]=N;
            }
        }
    }
    int solve(int s,int d){
        int res=n,x=1,ans=0,tot=s-1;
        for(int i=maxlen;i>=0;i--){
            if(tot>=(1<<i) && res>=f[x][i] && x<=n)
                tot-=(1<<i),res-=f[x][i],x+=f[x][i],ans+=(1<<i);
        }
        int pre=ans+d;
        if(!res)return pre;
        tot=d;
        for(int i=maxlen;i>=0;i--){
            if(tot>=(1<<i) && res>=g[x][i] && x<=n)
                tot-=(1<<i),res-=g[x][i],x+=g[x][i],ans+=(1<<i);
        }
        ans=Max(pre,ans);
        if(!res)return ans;
        for(int i=maxlen;i>=0;i--){
            if(res>=f[x][i] && x<=n)
                res-=f[x][i],x+=f[x][i],ans+=(1<<i);
        }
        return ans;
    }
    void work()
    {
        scanf("%d%d%d%d",&n,&W,&pw,&lw);
        maxlen=log(n)/log(2)+1;rw=W-pw-lw;
        for(int i=1;i<=n;i++)
            scanf("%d",&a[i]),sum[i]=sum[i-1]+a[i];
        prework();
        int Q,x,y;cin>>Q;
        while(Q--){
            scanf("%d%d",&x,&y);
            printf("%d
    ",solve(x,y));
        }
    }
    
    int main()
    {
        int T;cin>>T;
        while(T--)work();
        return 0;
    }
    
    
  • 相关阅读:
    NSInvocation 回调使用
    C#控制台源程序分享
    HTML 表单控件的汇总
    学习笔记(2):HTML 常用标签的归纳
    学习笔记(4):C#中的正则简单总结
    学习笔记(5):DIV+CSS 经典盒子模型 积累
    学习笔记(3):sql语句的总结
    毕业一年小结
    头文件方法问题
    百度被黑事件
  • 原文地址:https://www.cnblogs.com/Yuzao/p/7562294.html
Copyright © 2011-2022 走看看