zoukankan      html  css  js  c++  java
  • 抄书(Copying Books, UVa 714)

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

           多组案例,大意是说先给定两个数m和k,m表示数据个数,k表示将m个数据分为k份,要求划分后的子序列的和的最大值最小,每次划分尽量往右划分。1<=k<=m<=500,子序列和的最大值不超过10000000。

           输入:首行输入案例数,次行输入m和k(使用空格符分隔),第三行输入m个数据。

           输出:输出m个数据并在分割处使用'/'间隔。
    案例:

           Sample Input 

       2
       9 3
       100 200 300 400 500 600 700 800 900
       5 4
       100 100 100 100 100
    

         Sample Output

      100 200 300 400 500 / 600 700 / 800 900
      100 / 100 / 100 / 100 100

    分析:

           找子序列的和可以先从和的范围查找,容易判断该和的范围为原序列中最大的元素值至其整个序列的和,然后我们就可以利用二分法查找这个子序列的和的最大值的最小值了,查找划分最好从序列右端开始。
    源代码:

     1 #include<cstdio>
     2 #include<cstring>
     3 typedef long long ll;//声明定义ll表示long long型
     4 ll T,m,k,a[510],b[510],ans[510],left,right,mid;
     5 ll check(ll max)
     6 {
     7     ll j,num=0,tot=0;
     8     memset(b,0,sizeof(b));
     9     for(j=m;j>=1;j--)//由后往前查找'/'可摆放处
    10     {
    11         if(tot+a[j]<=max&&j>=k-num)//判断a[j]处能否继续摆放'/'
    12             tot+=a[j];
    13         else
    14         {
    15             ++num;//切割次数记录
    16             tot=a[j];
    17             b[j]=1;//测试设定'/'摆放标志
    18         }
    19     }
    20     if(num+1==k)//判断测试结果是否满足条件
    21     {
    22         for(j=1;j<=m;j++)
    23             ans[j]=b[j];
    24         return 1;
    25     }
    26     else return 0;
    27 }
    28 int main()
    29 {
    30     ll i;
    31     scanf("%lld",&T);//案例数
    32     while(T--)
    33     {
    34         left=0;
    35         right=0;
    36         scanf("%lld%lld",&m,&k);
    37         for(i=1;i<=m;i++)
    38         {
    39             scanf("%lld",&a[i]);
    40             right+=a[i];//将序列的和设为子序列和的最大限值
    41             if(a[i]>left) left=a[i];//将序列中最大的值设为子序列的最小限值
    42         }
    43         memset(ans,0,sizeof(ans));
    44         while(left<=right)//二分法查找最小的子序列的和
    45         {
    46             mid=(left+right)/2;
    47             if(check(mid)==1)
    48                 right=mid-1;
    49             else left=mid+1;
    50         }
    51         for(i=1;i<m;i++)//输出控制
    52         {
    53             if(ans[i]==1)
    54                 printf("%lld / ",a[i]);
    55             else printf("%lld ",a[i]);
    56         }
    57         printf("%lld
    ",a[m]);
    58     }
    59     return 0;
    60 }
  • 相关阅读:
    自定义组件 -- android联系人
    ListView嵌套出现的问题
    编译Speex生成so库文件(android-speex)
    MacOs终端忽略大小写
    Eclipse报错:Setting property 'source' to 'org.eclipse.jst.jee.server:test1' did no
    Eclipse 反编译插件安装jad
    spring默认启动位置以及contextConfigLocation设置源码解析
    git使用2
    Git常用命令
    spring MVC配置详解
  • 原文地址:https://www.cnblogs.com/huaszjh/p/4705130.html
Copyright © 2011-2022 走看看