zoukankan      html  css  js  c++  java
  • 【bzoj1044】木棍分割

    Description

      有n根木棍, 第i根木棍的长度为Li,n根木棍依次连结了一起, 总共有n-1个连接处. 现在允许你最多砍断m个连
    接处, 砍完后n根木棍被分成了很多段,要求满足总长度最大的一段长度最小, 并且输出有多少种砍的方法使得总长
    度最大的一段长度最小. 并将结果mod 10007。。。

    Input

      输入文件第一行有2个数n,m.接下来n行每行一个正整数Li,表示第i根木棍的长度.n<=50000,0<=m<=min(n-1,10
    00),1<=Li<=1000.

    Output

      输出有2个数, 第一个数是总长度最大的一段的长度最小值, 第二个数是有多少种砍的方法使得满足条件.

    Sample Input

    3 2
    1
    1
    10

    Sample Output

    10 2

    Solution

    第一问我们使用二分查找查询每个区间的长度上线是多少

    对于第二问,我们使用动态规划

    f[i][j]=simga(f[k][j-1])(s[i]-s[k]<=lim)

    显然的我们可以使用前缀和来解决问题

    然后对于每个i,k最小能取到多少是确定的,我们预处理一下,

    然后加个滚动数组就一遍a了,开心!

    #include<stdio.h>
    #include<stdlib.h>
    #include<iostream>
    #include<string>
    #include<string.h>
    #include<algorithm>
    #include<math.h>
    #include<queue>
    #include<map>
    #include<vector>
    #include<set>
    #define il inline
    #define re register
    #define mod 10007
    using namespace std;
    const int N=51111;
    int n,m,a[N],l=0,r=0,mid,s[N],lim,p[N],f[2][N],lst,now,ans;
    il bool chk(int lim){
        int cnt=0,tot=1;
        for(int i=1;i<=n;i++){
            if(cnt+a[i]<=lim){
                cnt+=a[i];
            }
            else{
                cnt=a[i];tot++;
            }
        }
        return tot<=m;
    }
    int main(){
        scanf("%d%d",&n,&m);m++;
        for(int i=1;i<=n;i++){
            scanf("%d",&a[i]);
            r+=a[i];l=max(l,a[i]);
        }
         
        while(l<r){
            mid=(l+r)/2;
            if(chk(mid)) r=mid;
            else l=mid+1;
        }
        lim=r;
        for(int i=1;i<=n;i++) s[i]=s[i-1]+a[i];
        for(int i=1;i<=n;i++){
            l=1;r=n;
            while(l<r){
                mid=(l+r)/2;
                if(s[i]-s[mid-1]<=lim) r=mid;
                else l=mid+1; 
            }
            p[i]=r; 
        }
        lst=0;now=1;
        for(int i=1;i<=n;i++) 
            if(s[i]<=lim) f[lst][i]=f[lst][i-1]+1;
            else f[lst][i]=f[lst][i-1];
        ans=(f[0][n]-f[0][n-1])%mod;
        for(int j=2;j<=m;j++){
            memset(f[now],false,sizeof(f[now]));
            for(int i=j,x;i<=n;i++){
                x=(f[lst][i-1]-f[lst][max(p[i]-2,0)])%mod;
                f[now][i]=(f[now][i-1]+x)%mod;
            }
            ans=(ans+f[now][n]-f[now][n-1]+mod)%mod;
            swap(now,lst);
        }
        cout<<lim<<" "<<ans;
        return 0;
    }
    
  • 相关阅读:
    给入坑前端的新人的建议
    浅析js闭包
    mongoose之操作mongoDB数据库
    input模拟输入下拉框
    浅析AngularJS自定义指令之嵌入(transclude)
    vue-cli之打包多入口配置
    Node.js之图片上传
    移动端之模态框滚动穿透问题
    浅谈vue之动态路由匹配
    vuex数据持久化存储
  • 原文地址:https://www.cnblogs.com/ExiledPoet/p/6091194.html
Copyright © 2011-2022 走看看