• JZOJ 8.15 B组总结


    NO.1 平台

    Description
      Alice要搭建平台,平台不能漂在空气中,必须要有两根柱子支撑,具体地说,每个平台的两端必须由一根柱子支撑,柱子的另一端在地板或另一个平台上。
      给你平台的放置位置(如下左图所示),每个平台的位置由它的高度(离地面的垂直距离)和水平方向两个端点的坐标决定,每根柱子必须安放在离端点0.5个单位的位置,如下右图所示。
      这里写图片描述

      编程计算所需柱子总长是多少。


    思路:暴力枚举
    暴力O(n^2)枚举,任意一个平台,对除它外的任意平台的贡献就好了


    代码:

    uses math;
    var n,i,lmax,rmax,j,ans:longint;
        h,l,r:array[0..101]of longint;
    begin
      readln(n);
      for i:=1 to n do readln(h[i],l[i],r[i]);
      for i:=1 to n do
        begin
          lmax:=h[i];
          rmax:=h[i];
          for j:=1 to n do
            if (i<>j)and(h[i]>h[j]) then
              begin
                if (l[i]<r[j])and(l[i]>=l[j]) then lmax:=min(lmax,h[i]-h[j]);
                if (r[i]>l[j])and(r[i]<=r[j]) then rmax:=min(rmax,h[i]-h[j]);
              end;
          ans:=ans+lmax+rmax;
        end;
      writeln(ans);
    end.
    

    NO.2 单足跳

    Description
      游戏在一行N个方块中进行,编号为1到N,一开始Alice在方块1中,第一次只能跳到方块2中,接下来每一次跳跃必须满足以下两个限制:
      (1) 如果是向前跳(即跳到比现在编号大的方块),跳跃距离必须比上一次要大1;
      (2) 如果是向后跳(即跳到比现在编号小的方块),跳跃距离必须跟上一次一样。
      例如,第一次跳跃后,Alice可以跳回1也可以跳到4。
      每进入一个方块,Alice必须支付一定的费用,Alice的目标花最少的钱从方块1跳到方块N。编程计算最小的花费。
    Input
      第一行包含一个整数N(2<=N<=1000),表示方块的个数。
      接下来N行,每行包含一个不超过500的正整数表示进入该方块的费用。
    Output
      输出Alice跳到N的最小花费。
    Sample Input

    输入1:
    6
    1
    2
    3
    4
    5
    6

    输入2:
    8
    2
    3
    4
    3
    1
    6
    1
    4

    Sample Output

    输出1:
    12

    输出2:
    14


    思路:dp
    设f[i][j]为跳了i步,当前在第j个格子的最小花费
    那么就枚举跳了多少步
    再转移一下就好了


    代码:

    var n,ans,i,j:longint;
        v:array[0..1001]of longint;
        f:array[0..1001,0..1001]of longint;
    begin
      readln(n);
      ans:=maxlongint;
      for i:=1 to n do readln(v[i]);
      fillchar(f,sizeof(f),$7f);f[1,2]:=v[2];
      for i:=1 to n-1 do
        begin
          for j:=n downto i+1 do if f[i,j]+v[j-i]<f[i,j-i] then f[i,j-i]:=f[i,j]+v[j-i];
          for j:=1 to n-i do if f[i,j]<>2139062143 then f[i+1,i+j+1]:=f[i,j]+v[i+j+1];
          if f[i,n]<ans then ans:=f[i,n];
        end;
      write(ans);
    end.

    NO.3 生日聚餐

    Description
      Alice在餐馆里当服务员,今天是她生日,她请求厨师帮她准备生日晚餐,晚餐由N种原料做成,每道菜所需每种原料的数量是一样的。
      厨房里有一些原料,但不够,Alice还需要从旁边的超市中购买一些回来。超市里什么原料都有,每种原料都分大包装和小包装。Alice有M元钱,她想利用这M元钱购买原料使得能做出最多的菜。
    Input
      第一行包含两个整数N和M(1<=N<=100,1<=M<=100000),接下来N行,每行包含6个正整数,用来描述这种原料的信息,具体如下:
      (1) X:10<=X<=100,表示一道菜中必须含有这种原料的数量;
      (2) Y:1<=Y<=100,表示这种原料厨房已有的数量;
      (3) Sm:1<=Sm<=100,表示超市里小包装中含有这种原料数量;
      (4) Pm:10<=Pm<=100,表示小包装的价格;
      (5) Sv:1<=Sv<=100,表示超市里大包装中含有这种原料数量;   
    (6) Pv:10<=Pv<=100,表示大包装的价格;
    Output
    输出最多能做多少道菜。
    Sample Input

    输入1:
    2 100
    10 8 10 10 13 11
    12 20 6 10 17 24

    输入2:
    3 65
    10 5 7 10 13 14
    10 5 8 11 14 15
    10 5 9 12 15 16

    Sample Output

    输出1:
    5

    输出2:
    2

    Hint
    【样例说明】
      样例1中,Alice购买第一种原料3个小包装和1个大包装,购买第二种原料1个小包装和2个大包装,一共花费3×10+1×11+1×10+2×24=99元。
      两种原料的数量分别为51个(8+3×10+11)和60个(20+1×6+2×17),可以做出5道菜。


    思路:二分+贪心
    每次二分求出一个mid,表示全部菜至少要做mid道
    再用贪心,求出每一道菜最小需要的钱数,加起来,判断一下是否符合条件,符合l=mid+1 不符合 r=mid


    代码:

    #include<cstdio>
    #include<iostream>
    using namespace std;
    int x[101],y[101],sm[101],pm[101],sv[101],pv[101],f[101][100001];
    int mid,n,m,l,r;
    bool pd(int q)
    {
        int s[101],k,ans,sum=0;
        for (int i=1;i<=n;i++) s[i]=q*x[i]-y[i];
        for (int i=1;i<=n;i++)
        {   
            ans=2147483647;
            for (int j=0;j<=s[i]/sm[i]+2;j++)
            {
                if (s[i]-j*sm[i]>0) k=(s[i]-sm[i]*j-1)/sv[i]+1; else k=0;
                ans=min(ans,j*pm[i]+k*pv[i]);
                if (j*pm[i]>=ans) break;
            }
            sum+=ans;
            if (sum>m) return false;
        }
        if (sum<=m) return true;
    }
    int main()
    {
        scanf("%d%d",&n,&m);
        for (int i=1;i<=n;i++) scanf("%d%d%d%d%d%d",&x[i],&y[i],&sm[i],&pm[i],&sv[i],&pv[i]);
        l=0; r=m;
        while (l<r)
        {
            mid=(l+r)>>1;
            if (pd(mid)) l=mid+1; else r=mid;
        }
        printf("%d
    ",l-1);
        return 0;
    }

    NO.4 数学题

    Description
      当Alice在浏览数学书时,看到一个等式A=S,奇怪的是A和S并不相等。Alice发现可以通过在A中添加加号“+”从而使得等式成立。
      编程计算最少需要插入多少加号使得等式成立。允许每个数有多个前导0。
    Input
      输入第一行包含一个等式形式为A=S。
      A和S都是没有前导0的正整数,并保证不相同。
      A最多有1000位。
      S<=5000。
      输入保证有解。
    Output
      输出最少需要插入的加号数量。
    Sample Input

    输入1:
    143175=120

    输入2:
    5025=30

    输入3:
    999899=125

    Sample Output

    输出1:
    2

    输出2:
    1

    输出3:
    4


    思路:DP
    设f[i][j]为前i位和为j需要的最少加号个数
    f[l,j+sum]:=min(f[l,j+sum],f[i,j]+1);
    if (j+sum=n)and(l=k) then ans:=min(ans,f[i,j]);
    l为枚举到第l位,sum为第i~l位的数字和,k为a的长度


    代码:

    uses math;
    var s,st,s2:ansistring;
        s1:string[1];
        a:array[0..1000]of longint;
        f:array[0..1000,0..5000]of longint;
        i,j,k,m,n,t,ans,l,sum,p,w:longint;
    
    procedure init;
    begin
      readln(s);
      st:=copy(s,1,pos('=',s)-1);
      val(copy(s,pos('=',s)+1,length(s)),n);
      for i:=1 to length(st) do
        begin
          k:=k+1;
          a[k]:=ord(s[i])-48;
        end;
      for i:=0 to 1000 do for j:=0 to 5000 do f[i,j]:=maxlongint;
      f[0,0]:=0;
      ans:=maxlongint;
    end;
    
    function make:longint;
    begin
      s2:='';
      for p:=t to l do
        begin
          str(a[p],s1);
          s2:=s2+s1;
        end;
      val(s2,sum);
      if j+sum<=n then
        begin
          f[l,j+sum]:=min(f[l,j+sum],f[i,j]+1);
          if (j+sum=n)and(l=k) then ans:=min(ans,f[i,j]);
        end
      else exit(1);
      exit(0);
    end;
    
    begin
      init;
      for i:=0 to k do
        for j:=0 to n do
          if f[i,j]<maxlongint then
            begin
              t:=i+1;
              while (a[t]=0)and(t<k) do t:=t+1;
              w:=min(k,t+length(st));
              for l:=t to w do if make=1 then break;
            end;
      writeln(ans);
    end.
  • 相关阅读:
    Server Application Unavailable 解决办法 (转)
    SQL SERVER:分割函数 split
    Win32汇编_基础
    Win32汇编_异常_筛选器
    创建进程常用函数
    内存常用函数
    桃花庵歌
    文天祥的诗
    Socket I/O模型全接触
    函数指针的神奇
  • 原文地址:https://www.cnblogs.com/Comfortable/p/8412255.html
Copyright © 2020-2023  润新知