zoukankan      html  css  js  c++  java
  • BZOJ 1044 HAOI2008 木棍切割 二分答案+动态规划

    题目大意:给定n个连在一起的木棍。分成m+1段。使每段最大值最小,求最大值的最小值及最大值最小时切割的方案数

    第一问水爆了……二分答案妥妥秒过

    第二问就有些难度了 首先我们令f[i][j]表示用前j个棒♂子得到i段的方案数

    诶我没打什么奇怪的符号吧

    于是我们有动规方程

    f[i][j]=Σf[i-1][k] (sum[j]-sum[k]<=ans,k<j)

    这个最坏情况下是O(m*n^2)的,肯定挂

    我们发现k的下界是单调上升的 于是我们直接令k为当前j时k的下界。开一个变量记录k~j的f值之和

    每次j++时将k向后调整 此外f数组要开滚动数组不然MLE

    写完交上去各种神慢……搞不懂其它人都写了啥

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #define M 50500
    #define Mo 10007
    using namespace std;
    int n,m,limit,ans;
    int maxlen=0,a[M],sum[M];
    int f[2][M];
    inline bool Judge(int x)
    {
    	int i,re=0,now=x;
    	for(i=1;i<=n;i++)
    	{
    		if(now+a[i]>x)
    			++re,now=a[i];
    		else
    			now+=a[i];
    		if(re>m)
    			return false;
    	}
    	return true;
    }
    inline int Bisection()
    {
    	int l=maxlen,r=sum[n];
    	while(l+1<r)
    	{
    		int mid=l+r>>1;
    		if( Judge(mid) )
    			r=mid;
    		else
    			l=mid;
    	}
    	if( Judge(l) )
    		return l;
    	return r;
    }
    int main()
    {
    	int i,j,k;
    	cin>>n>>m;++m;
    	for(i=1;i<=n;i++)
    		scanf("%d",&a[i]),sum[i]=sum[i-1]+a[i],maxlen=max(maxlen,a[i]);
    	limit=Bisection();
    	f[0][0]=1;
    	for(i=1;i<=m;i++)
    	{
    		int temp=0;k=i-2;
    		for(j=i;j<=n;j++)
    		{
    			temp+=f[~i&1][j-1],temp%=Mo;
    			while(sum[j]-sum[k+1]>limit)
    				temp+=Mo-f[~i&1][++k],temp%=Mo;
    			f[i&1][j]=temp;
    		}
    		ans+=f[i&1][n],ans%=Mo;
    	}
    	cout<<limit<<' '<<ans<<endl;
    }
    


  • 相关阅读:
    Java--强制转化
    Java--成绩分类
    建造者模式的应用
    抽象工厂模式的应用
    工厂模式
    第几天
    Stacking Plates(存档待续.....(没有写思路和程序))
    圆的面积
    公孙策和陆湘湘对话(少年包青天第二部第二十集末尾和第二十一集开头部分)
    简单接口回调例子
  • 原文地址:https://www.cnblogs.com/mfmdaoyou/p/6883025.html
Copyright © 2011-2022 走看看