洛谷1281 书的复制

题目:https://www.luogu.org/problemnew/show/P1281

很容易想到模板:乘积最大

f[i,j]=min(max(f[k-1,j-1],sum[k...i]))  循环k:最后一个人复制k~i的书

f[i,j] 前i本书j个抄写员最短的最长用时。。。二维就可以了

50分代码:

#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;

const int maxSize=500,maxValue=0x7fffffff;
int m,k1;
int a[maxSize+5],sum[maxSize+5],f[maxSize+5][maxSize+5];//前i本书j个人写 
int ans[maxSize+5][maxSize+5],ans1[maxSize+5];

void dp()
{
	int i,j,k,max1,temp;
	
	for (j=1;j<=k1;j++)//前j个抄写员 
	{
		for (i=j;i<=m;i++)//i本书 
		{
			if (j==1)
			{
				f[i][1]=sum[i];
				continue;
			}
			f[i][j]=maxValue;
			for (k=j;k<=i;k++)//k:最后一个人拿的第一本 
			{
				max1=max(f[k-1][j-1],sum[i]-sum[k-1]);
				if (f[i][j]>max1)
				{
					f[i][j]=max1;
					ans[i][j]=k;
				}
			}
		}
	}
	temp=m;
	for (i=k1;i>1;i--)
	{
		ans1[i]=ans[temp][i]-1;
		temp=ans1[i];
	}
	temp=1;	ans1[k1+1]=m;
	for (i=1;i<=k1;i++)
	{
//		printf("%d\n",ans1[i]);
		printf("%d %d\n",temp,ans1[i+1]);
		temp=ans1[i+1]+1;
	}
}

int main()
{
	int i;
	
	freopen("a.txt","r",stdin);
	scanf("%d%d",&m,&k1);
	memset(a,0,sizeof(a));
	memset(f,0,sizeof(f));
	memset(sum,0,sizeof(sum));
	for (i=1;i<=m;i++)
	{
		scanf("%d",&a[i]);
		sum[i]=sum[i-1]+a[i];
	}
	dp();
	
	
	return 0;
}

输出有问题。。。要求越后面的人尽可能多的复制书。。。

用一波贪心。。。从后往前搜小于答案的

	an=f[m][k1];
	temp=m;	j=k1;
	for (i=m;i>=1;i--)
	{
		if (sum[temp]-sum[i-1]>an)
		{
			ans1[j]=i+1;
			temp=i;
			j--;
			if (j==1)
				break;
		}
	}
	ans1[1]=1;	ans1[k1+1]=m+1;
	for (i=1;i<=k1;i++)
	{
		printf("%d %d\n",ans1[i],ans1[i+1]-1);
	}

猜你喜欢

转载自blog.csdn.net/scutbenson/article/details/82026358