zoukankan      html  css  js  c++  java
  • 1044: [HAOI2008]木棍分割

    Description

    有n根木棍, 第i根木棍的长度为Li,n根木棍依次连结了一起, 总共有n-1个连接处. 现在允许你最多砍断m个连接处, 砍完后n根木棍被分成了很多段,要求满足总长度最大的一段长度最小, 并且输出有多少种砍的方法使得总长度最大的一段长度最小. 并将结果mod 10007。。。
    Input

    输入文件第一行有2个数n,m. 接下来n行每行一个正整数Li,表示第i根木棍的长度.
    Output

    输出有2个数, 第一个数是总长度最大的一段的长度最小值, 第二个数是有多少种砍的方法使得满足条件.
    Sample Input
    3 2
    1
    1
    10
    Sample Output
    10 2

    两种砍的方法: (1)(1)(10)和(1 1)(10)
    数据范围
    n<=50000, 0<=m<=min(n-1,1000).
    1<=Li<=1000.

    第一问就直接二分答案

    第二问我们动态规划,f[i,j]表示前i个分成j段有多少种方案

    f[i,j]=sigema(f[k,j-1])(sum[i]-sum[k]<=lim)

    数组要滚动,每次计算f[i,j]时先继承f[i+1,j]的值(因为我是倒着做的),然后把多的减去少的加上就行了

     1 const
     2     maxn=100010;
     3     h=10007;
     4 var
     5     f,a,s:array[0..maxn]of longint;
     6     n,m,lim,ans:longint;
     7  
     8 function flag(x:longint):boolean;
     9 var
    10     i,k,sum:longint;
    11 begin
    12     k:=0;
    13     sum:=0;
    14     for i:=1 to n do
    15       begin
    16         if a[i]>x then exit(false);
    17         if sum+a[i]>x then
    18           begin
    19             inc(k);
    20             sum:=a[i];
    21           end
    22         else inc(sum,a[i]);
    23       end;
    24     if sum>0 then inc(k);
    25     if k>m then exit(false);
    26     exit(true);
    27 end;
    28  
    29 procedure init;
    30 var
    31     i,l,r,mid:longint;
    32 begin
    33     read(n,m);
    34     inc(m);
    35     for i:=1 to n do
    36       begin
    37         read(a[i]);
    38         s[i]:=s[i-1]+a[i];
    39       end;
    40     l:=1;
    41     r:=500000000;
    42     while l<>r do
    43       begin
    44         mid:=(l+r)>>1;
    45         if flag(mid) then r:=mid
    46         else l:=mid+1;
    47       end;
    48     lim:=l;
    49     f[0]:=1;
    50     write(lim,' ');
    51 end;
    52  
    53 procedure work;
    54 var
    55     i,j,l,sum:longint;
    56 begin
    57     for i:=1 to m do
    58       begin
    59         sum:=f[n];
    60         l:=n-1;
    61         for j:=n downto 0 do
    62           begin
    63             dec(sum,f[j]);
    64             f[j]:=0;
    65             while (l>=0) and (s[j]-s[l]<=lim) do
    66               begin
    67                 inc(sum,f[l]);
    68                 dec(l);
    69               end;
    70             f[j]:=sum mod h;
    71           end;
    72         ans:=(ans+f[n])mod h;
    73       end;
    74     write(ans);
    75 end;
    76  
    77 begin
    78     init;
    79     work;
    80 end.
    View Code
  • 相关阅读:
    SCRUM项目 4.0
    【操作系统】实验三 进程调度模拟程序
    Spring 计划
    backlog
    0505-NABCD模型、视频
    0429团队准备
    1028 C语言文法
    编译原理第二次作业 编译器任务总结
    1014编译原理第二次作业(修改版)
    算法原理与分析第二次作业
  • 原文地址:https://www.cnblogs.com/Randolph87/p/3650325.html
Copyright © 2011-2022 走看看