[JZOJ P1264] [DP]复制书稿

@Kaike

传送门

一道经典DP,可是书上看不懂,并且代码也是错的。(orz 我错辣)

大概这有几点要求:

1.m本书是顺序排列的,k个抄写员选择书也是顺序且连续的。

2.输出方案,并保证前面的人少抄一点,贪心,让后面的人尽可能多抄一点。

我们可以先枚举人数i,再枚举书的数量j,最后将书的数量j分为两部分,一部分有i-1个人写,另一部分由1个人去写

比较这两种情况下哪一种的书的数量比较大,即是求出了在分割书数量不同的情况下,每次复制的时间

将这些不同分割方法的各个时间都计算出来以后,与相同阶段的所有时间进行比较,取其中的最小值,这个值就是要求得的最小复制时间

f[i,j]=min(f[i,j],max(f[i-1,l],sum[l+1,j]))

 

1 for(int i=2;i<=k;i++)  //枚举人数;
2     for(int j=1;j<=m;j++)  //枚举书的总数;
3         for(int t=1;t<j;t++)  //在不同的位置将书分割为两个部分,然后求取最大值,这里的最大值就是该种分割方案下的复制时间;
4             f[i][j]=min(f[i][j],max(f[i-1][t],sum[j]-sum[t]));  //初次理解很别扭,静心想想

 

 1 #include<iostream>
 2 #include<algorithm>
 3 #include<cstring>
 4 using namespace std;
 5 int m,k,f[510][510],a[510],sum[510];
 6 void init()
 7 {
 8     memset(f,10,sizeof(f));
 9     memset(sum,0,sizeof(sum));
10     cin>>m>>k;
11     for(int i=1;i<=m;i++)
12     {
13         cin>>a[i];
14         sum[i]=sum[i-1]+a[i];  //记录前i本书的总页数;
15         f[1][i]=sum[i];  //一个人抄i本书的时间;
16     }
17 }
18 void work()
19 {
20     for(int i=2;i<=k;i++)
21         for(int j=1;j<=m;j++)
22             for(int t=1;t<j;t++)
23                 f[i][j]=min(f[i][j],max(f[i-1][t],sum[j]-sum[t]));
24 }
25 void print(int i,int j)
26 {
27     if(i==0)  return;
28     if(i==1)  
29     {cout<<1<<' '<<i<<endl; return ;}
30     else
31     {
32         int temp=i,x=a[i];
33         while(x+a[temp-1]<=f[k][m] && temp>1)
34             x+=a[--temp];
35         print(temp-1,j-1);
36         cout<<temp<<' '<<i<<endl;
37     }
38 }
39 int main()
40 {
41     init();
42     work();
43     print(m,k);
44     return 0;
45 }
= =

你是不是wa了好几次

你是不是哭着说教材错了

你是不是看不懂写的什么

滚去写代码啊

少个memset这么多废话!

No matter how you feel, get up , dress up , show up ,and never give up.
原文地址:https://www.cnblogs.com/Kaike/p/5937522.html