Description
Robby bought a new bookshelf, and he wanted to put all his N books on it. The bookshelf contains K layers,
and the heights of each layer are variable. That is, the minimum height of one layer is equal to the maximum
height of all the books in this layer. And the height of the bookshelf is the sum of all layers' heights.
Now Robby wants to make the height of his bookshelf as low as possible, but he don't want to break the order
of the books, that is, each layer must contain the consecutive books of the original book series. And each
layer must contain at least one book.
Input
There are several test cases in the input.
The first line of each test case contains two integers N and K (1 ≤ K ≤ N ≤ 100).
The second line contains N integers, indicating the heights of the books. You can assume
the height of every book is no more than 1000.
The input is terminated with N = K = 0.
Output
Output one line for each test case, that is, the minimum height of the bookshelf.
Sample Input
4 2
1 4 2 3
4 2
4 1 2 3
4 4
1 2 3 4
0 0
Sample Output
5
7
10
Hint
For the first sample, the best strategy is 1+max(4,2,3)=5
For the second sample, the best strategy is max(4,1,2)+3=7
For the third sample, the best strategy is 1+2+3+4=10
Source
TJU Programming Contest 2007 by RoBa
有序的划分模型
关键是要确定第i本书要放到那层书架上。
另dp[i][j]为第i本书放到第j层书架上时的总高度的最小值。
则dp[n][k]即为所求。
dp[i][0]=INF
对于第i本书,能放到的书架层数x是有个范围的。
对于第x层书架,能放进去的书也是有个范围的。
dp[i][j]=min{dp[k-1][j-1]+M[k][i],k>=j&&k<=i}
①单独放到j层书架上。
②第k本书到第i本书放到第j层书架上。
取最小值
其中M[k][i]需要预处理出来第k本书到第i本书之间(包含)的最大书本高度。
因此算法复杂度为O(n^3).
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int n,m,a[105],mm[105][105],dp[105][105];
int main()
{
while(scanf("%d%d",&n,&m),n+m)
{
int i,j,k;
for(i=1;i<=n;i++)
scanf("%d",a+i);
memset(dp,0,sizeof(dp));
for(i=1;i<=n;i++)
{
mm[i][i]=a[i];
dp[i][0]=999999999;
for(j=i+1;j<=n;j++)
{
mm[i][j]=mm[i][j-1];
if(a[j]>mm[i][j-1])
mm[i][j]=a[j];
}
}
for(i=1;i<=n;i++)
for(j=max(1,m+i-n);j<=i;j++)
{
int t=999999999;
for(k=j;k<=i;k++)
if(dp[k-1][j-1]+mm[k][i]<t)
t=dp[k-1][j-1]+mm[k][i];
dp[i][j]=t;
}
printf("%d/n",dp[n][m]);
}
}