zoukankan      html  css  js  c++  java
  • [BZOJ 1044][HAOI2008]木棍分割(二分+Dp)

    Description

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

    Solution

    二分答案求最小化的最大长度,然后Dp方案数

    dp[i][j]表示前i个物品砍j刀保持最大长度不超过ans的方案数

    dp[i][j]=∑dp[k][j-1](∑L[l]<=ans k+1<=l<=i)

    发现时间空间都要优化

    O(n^2m)肯定T了 但是可以知道k是单调递增的 于是用了一个dp[][j-1]的前缀和pre[]随便搞搞,当然也可以单调队列做

    空间的话开滚动数组就好了

    【然而我滚的时候忘记清零,WAWAWAQAQ,而且只WA一个点,拍了半天没拍出来】

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<queue>
    #define Min(a,b) (a<b?a:b)
    #define Max(a,b) (a>b?a:b)
    #define Mod 10007
    using namespace std;
    int n,m,L[50005],sum[50005],pre[50005],dp[50005][2];
    int Read()
    {
        int x=0,f=1;char c=getchar();
        while(c<'0'||c>'9'){
            if(c=='-')f=-1;c=getchar();
        }
        while(c>='0'&&c<='9'){
            x=x*10+c-'0';c=getchar();
        }
        return x*f;
    }
    bool check(int x)
    {
        int len=0,cnt=0;
        for(int i=1;i<=n;i++)
        {
            if(len+L[i]>x)cnt++,len=0;
            len+=L[i];
        }
        if(cnt>m)return false;
        return true;
    }
    int main()
    {
        n=Read(),m=Read();
        int l=1,r,ans;
        for(int i=1;i<=n;i++)
        {
            L[i]=Read();
            sum[i]=sum[i-1]+L[i];
            l=Max(l,L[i]);
        }
        r=sum[n];
        while(l<=r)
        {
            int mid=(l+r)>>1;
            if(check(mid))ans=mid,r=mid-1;
            else l=mid+1;
        }
        int cur=0,tot=0;
        for(int i=1;i<=n;i++)
        if(sum[i]<=ans)dp[i][0]=1;
        for(int j=1;j<=m;j++)
        {
            cur^=1;
            for(int i=1;i<=n;i++)
            pre[i]=pre[i-1]+dp[i][cur^1];
            for(int i=1;i<=n;i++)
            dp[i][cur^1]=0;
            int k=1;
            for(int i=1;i<=n;i++)
            {
                while(sum[i]-sum[k]>ans&&k<i)
                k++;
                dp[i][cur]+=pre[i-1]-pre[k-1],dp[i][cur]%=Mod;
            }
            tot=(tot+dp[n][cur])%Mod; 
        }
        printf("%d %d
    ",ans,tot);
        return 0;
    }
  • 相关阅读:
    tomcat---基本知识点解读;配置文件详解
    nginx常用配置参数介绍-upstream
    nginx配置文件-详解
    nginx简单介绍
    GCC编译已经引入math.h文件提示cos,sin等函数未定义
    进程与进程间通信(3)
    进程与进程间通信(1)
    进程与进程间通信(2)
    primer_c++_迭代器
    primer_C++_3.5 数组
  • 原文地址:https://www.cnblogs.com/Zars19/p/6701005.html
Copyright © 2011-2022 走看看