zoukankan      html  css  js  c++  java
  • Copying Books

    题目链接:http://acm.hust.edu.cn/vjudge/contest/view.action?cid=85904#problem/B

    题意:

          把一个包含m个正整数的序列划分成k个(1<=k<=m<=500)非空的连续子序列,使得每个正整数恰好属于一个序列。设第i个序列的各数之和为s(i),让所有s(i)的最大值尽量小。

          如果划分序列最大值相等,就从第一个划分开始让前面的划分尽量小。

          案例:

          input

          2

          9 3

          100 200 300 400 500 600 700 800 900

          5 4

          100 100 100 100 100

          output

          100 200 300 400 500 / 600 700 / 800 900

          100 / 100 / 100 / 100 100

    思路分析:

           利用二分法,先找出最大值的可能区间。

           因为它要让前面的划分尽量小,那么要利用贪心法从右边开始往前遍历进行划分区间,只要其总和不大于之前所求的最大值,就归到那个区间,同时找出“/”所在的地方。但是只有一个条件还不能找出所有“/”,如例2就只有后面2个“/”,所以加上i==x-1,即可。(x=k-1)

    源代码如下:

     1 #include<iostream>
     2 #include<cstring>
     3 using namespace std;
     4 int m,k,c[505],s[505];
     5 long long M;
     6 bool judge(long long mid)     //判断最大值在左区间还是右区间
     7 {
     8     int sum=0,t=k;
     9     for(int i=0;i<m;i++)
    10     {
    11         sum+=s[i];
    12         if(sum>mid)
    13         {
    14             i--;
    15             sum=0;
    16             t--;
    17         }
    18         if(!t)
    19         {
    20             if(i!=m-1)return false;
    21             else return true;
    22         }
    23     }
    24     return true;
    25 }
    26 void min_max()
    27 {
    28     memset(c,0,sizeof(c));
    29     long long l,r,mid;
    30     int i;
    31     l=0;r=M;
    32     while(l<r)            //判断最小最大值所在区间
    33     {
    34         mid=(l+r)/2;
    35         if(judge(mid)) r=mid;
    36         else l=mid+1;
    37     }
    38     int sum=0,x=k-1;
    39     for(i=m-1;i>=0;i--)        //从右边开始确定划分
    40     {
    41         sum+=s[i];
    42         if(sum>r||i==x-1)
    43         {
    44             sum=0;
    45             c[++i]=1;          //确定“/”的位置
    46             x--;
    47         }
    48     }
    49     cout<<s[0];
    50     for(i=1;i<m;i++)       
    51     {
    52         if(c[i])cout<<" /";
    53         cout<<" "<<s[i];
    54     }
    55     cout<<endl;
    56 }
    57 int main()
    58 {
    59     int N;
    60     cin>>N;
    61     while(N--)
    62     {
    63         M=0;
    64         cin>>m>>k;
    65         for(int i=0;i<m;i++)
    66         {
    67             cin>>s[i];
    68             M+=s[i];
    69         }
    70         min_max();
    71     }
    72     return 0;
    73 }

          

  • 相关阅读:
    onSaveInstanceState和onRestoreInstanceState()
    Android TextView中文字通过SpannableString来设置超链接、颜色、字体等属性
    又优化了一下 Android ListView 异步加载图片
    ListView异步加载图片
    SpannableString 设置一段文字中部分字体颜色
    Android Studio apk 打包流程
    svn分支开发与主干合并(branch & merge)
    SVN使用教程之——分支、合并
    XMPP协议实现原理介绍
    监听器
  • 原文地址:https://www.cnblogs.com/q-c-y/p/4702337.html
Copyright © 2011-2022 走看看