[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.