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;
}
时间: 2024-08-27 17:56:59

BZOJ 1044 HAOI2008 木棍分割 二分答案+动态规划的相关文章

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值之和

bzoj 1044 [HAOI2008]木棍分割(二分+贪心,DP+优化)

[题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=1044 [题意] n根木棍拼到一起,最多可以切m刀,问切成后最大段的最小值及其方案数. [思路] 对于第一问可以二分后贪心判断. 假设第一问得到的答案为L,设f[i][j]前i个木棍切j下且保持段长不超过L的方案数,则有转移式: f[i][j]=sigma { f[k][j-1] },k<i,suma(k+1,i)<=L 优化:  空间方面可以用个滚动数组. 时间方面由于前缀和sum

【BZOJ】1044: [HAOI2008]木棍分割 二分+区间DP

链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1044 Description 有n根木棍, 第i根木棍的长度为Li,n根木棍依次连结了一起, 总共有n-1个连接处. 现在允许你最多砍断m个连接处, 砍完后n根木棍被分成了很多段,要求满足总长度最大的一段长度最小, 并且输出有多少种砍的方法使得总长度最大的一段长度最小. 并将结果mod 10007... Input 输入文件第一行有2个数n,m. 接下来n行每行一个正整数Li,表示第i根木棍

bzoj 1044: [HAOI2008]木棍分割

2016-06-20 第一问是个二分的经典入门题 第二问很容易发现一个DP f[i][j]前i个木棍分j次合法方案数,f[i][j]=f[k][j-1]+...+f[i-1][j-1]; 但这样时间复杂度是O(mn^2),空间复杂度是O(mn) 但我们发现对于相同的j随着i的增加,对应的k也增加,那我们可以根据这个单调性,用前缀和来做到转移复杂度为O(1),空间可以用滚动数组来解决,本来我偷懒用short int开数组,不用滚动数组.结果T了一半,早就听说数组大了会使程序变慢,今天我可算知道了,

1044: [HAOI2008]木棍分割

1044: [HAOI2008]木棍分割 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 2161  Solved: 779[Submit][Status][Discuss] Description 有n根木棍, 第i根木棍的长度为Li,n根木棍依次连结了一起, 总共有n-1个连接处. 现在允许你最多砍断m个连接处, 砍完后n根木棍被分成了很多段,要求满足总长度最大的一段长度最小, 并且输出有多少种砍的方法使得总长度最大的一段长度最小. 并将结果m

【bzoj1044】[HAOI2008]木棍分割 二分+dp

题目描述 有n根木棍, 第i根木棍的长度为Li,n根木棍依次连结了一起, 总共有n-1个连接处. 现在允许你最多砍断m个连接处, 砍完后n根木棍被分成了很多段,要求满足总长度最大的一段长度最小, 并且输出有多少种砍的方法使得总长度最大的一段长度最小. 并将结果mod 10007... 输入 输入文件第一行有2个数n,m.接下来n行每行一个正整数Li,表示第i根木棍的长度.n<=50000,0<=m<=min(n-1,1000),1<=Li<=1000. 输出 输出有2个数,

bzoj1044[HAOI2008]木棍分割 单调队列优化dp

1044: [HAOI2008]木棍分割 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 4314  Solved: 1664[Submit][Status][Discuss] Description 有n根木棍, 第i根木棍的长度为Li,n根木棍依次连结了一起, 总共有n-1个连接处. 现在允许你最多砍断m个连接处, 砍完后n根木棍被分成了很多段,要求满足总长度最大的一段长度最小, 并且输出有多少种砍的方法使得总长度最大的一段长度最小. 并将结果

BZOJ1044: [HAOI2008]木棍分割

1044: [HAOI2008]木棍分割 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 1580  Solved: 567[Submit][Status] Description 有n根木棍, 第i根木棍的长度为Li,n根木棍依次连结了一起, 总共有n-1个连接处. 现在允许你最多砍断m个连接处, 砍完后n根木棍被分成了很多段,要求满足总长度最大的一段长度最小, 并且输出有多少种砍的方法使得总长度最大的一段长度最小. 并将结果mod 10007.

[HAOI2008]木棍分割解题报告

305 . [HAOI2008] 木棍分割 ★★★☆ 输入文件:stick.in 输出文件:stick.out 简单对比 时间限制:3 s 内存限制:64 MB [问题描述] 有n根木棍,第i根木棍的长度为Li,n根木棍依次连结在一起,总共有n-1个连接处.现在允许你最多砍断m个连接处,砍完后n根木棍被分成了很多段,要求满足总长度最大的一段长度最小,并且输出有多少种砍木棍的方法使得总长度最大的一段长度最小. [输入格式] 输入文件第一行有2个数n,m 接下来n行每行一个正整数Li,表示第i根木棍