(1544): 序列划分(求极大值的最小值)&(1233): 【基础算法】 书的复制

    xiaoxiao2021-12-14  23

    为什么要把这两道题放到一起写呢?就是因为这两道题很像很像只有输不输出方案的区别~

    不信把两道题目一起放出来!!

     

    问题 B(1544): 序列划分(求极大值的最小值)

    时间限制: 1 Sec  内存限制: 64 MB

    题目描述

    把一个包含n个正整数的序列划分为m个连续的子序列(子序列不能重叠)。设第i个序列的各数之和为S(i),你的任务是让所有S(i)的极大值尽量小。例如序列1 2 3 2 5 4划分为3个序列的最优方案为123|25|4,其中S(1),S(2),S(3)分别为6,7,4,极大值为7;如果划分为12|32|54,则极大值为9,不如刚才的好。N<1000000,所有数的和不超过10^9.

    输入

    输入数据: 第一行:两个正整数n,m。 第二行:n个正整数,表示该序列。

    输出

    输出数据: 最小的极大序列和

    样例输入

     

    Copy (如果复制到控制台无换行,可以先粘贴到文本编辑器,再复制)

    6 3 1 2 3 2 5 4

    样例输出

    7

    提示

     

    提示: 序列1 2 3 2 5 4划分为3个序列的最优方案为123|25|4,其中S(1),S(2),S(3)分别为6,7,4,极大值为7。其他的方案得到的极大值都大于7.所以输出7.

    问题 D(1233): 【基础算法】 书的复制

    时间限制: 1 Sec  内存限制: 64 MB

    题目描述

    现在要把m本有顺序的书分给k给人复制(抄写),每一个人的抄写速度都一样,一本书不允许给两个(或以上)的人抄写,分给每一个人的书,必须是连续的,比如不能把第一、第三、第四本书给同一个人抄写。 现在请你设计一种方案,使得复制时间最短。复制时间为抄写页数最多的人用去的时间。

    输入

    第一行两个整数m,k;(k≤m≤500) 第二行m个整数,第i个整数表示第i本书的页数。

    输出

    共k行,每行两个整数,第i行表示第i个人抄写的书的起始编号和终止编号。k行的起始编号应该从小到大排列,如果有多解,则尽可能让前面的人少抄写。

    样例输入

    Copy (如果复制到控制台无换行,可以先粘贴到文本编辑器,再复制)

    9 3 1 2 3 4 5 6 7 8 9

    样例输出

    1 5 6 7 8 9

     

    这就是hin典型的二分答案的题~2~1嘛~

    BUT!!!!!what is erfen??

    所谓二分,就是把一个区间对折对折再对折~~

    这样做的前提,就是你可以知道对折后该走哪一边~~

    算了直接给你们领略一下代码~

     

    #include<cstdio> int n,m,a[1000005],s; int sc(int bg,int ed) { if(bg==ed) return bg; int mid=(bg+ed)/2; int i,j=1,k=0,f=0; for(i=n;i>=1;i--) { if(a[i]>mid) { f=1;break; } if(k+a[i]>mid) { j++; k=0; } if(j>m) { f=1;break; } k+=a[i]; } if(f) return sc(mid+1,ed); else return sc(bg,mid); } int main() { int i; scanf("%d%d",&n,&m); for(i=1;i<=n;i++) { scanf("%d",&a[i]); s+=a[i]; } printf("%d",sc(0,s)); } /************************************************************** Problem: 1544 User: C20172037dza Language: C++ Result: 正确 Time:290 ms Memory:4936 kb ****************************************************************/

     

    #include<cstdio> #include<cstring> int n,m,a[505],s,p[505],q[505],p1[505],q1[505]; void sc(int bg,int ed) { int mid=(bg+ed)/2; int i,j,k=0; q1[1]=n; for(i=n,j=1;i>=1&&j<=m&&a[i]<=mid;i--) { if(k+a[i]>mid) { p1[j]=i+1; q1[j+1]=i; j++; k=0; } k+=a[i]; } p1[m]=1; if(bg==ed) { memcpy(p,p1,sizeof(p1)); memcpy(q,q1,sizeof(q1)); return; } if(j>m||a[i]>mid) sc(mid+1,ed); else sc(bg,mid); } int main() { int i; scanf("%d%d",&n,&m); for(i=1;i<=n;i++) { scanf("%d",&a[i]); s+=a[i]; } sc(0,s); for(i=m;i>0;i--) printf("%d %d\n",p[i],q[i]); } /************************************************************** Problem: 1233 User: C20172037dza Language: C++ Result: 正确 Time:0 ms Memory:1040 kb ****************************************************************/

    你们会发现,我只把输出方案的部分添加了,别的动了很少~~

     

    话说我做1544的时候没有判断

     

    if(a[i]>mid) { f=1;break; }if(a[i]>mid) { f=1;break; }

    于是hin华丽地WA了= =真tmd快啊..

     

    我也是在单步调试的时候发现的这个问题..

    简直了..pen pineapple apple pen

    果然还是要多测几组数据,不能过个样例就屁颠屁颠去提交= =

    然后1233就是说如果多解就让前面的人少抄就是让后面的多抄嘛~~

    然后二分能不能取mid要慎重考虑!!慎重考虑!!慎重考虑!!

    剩下的等我AC再说...

    转载请注明原文地址: https://ju.6miu.com/read-971316.html

    最新回复(0)