zoukankan      html  css  js  c++  java
  • 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.
  • 相关阅读:
    POJ3159 Candies —— 差分约束 spfa
    POJ1511 Invitation Cards —— 最短路spfa
    POJ1860 Currency Exchange —— spfa求正环
    POJ3259 Wormholes —— spfa求负环
    POJ3660 Cow Contest —— Floyd 传递闭包
    POJ3268 Silver Cow Party —— 最短路
    POJ1797 Heavy Transportation —— 最短路变形
    POJ2253 Frogger —— 最短路变形
    POJ1759 Garland —— 二分
    POJ3685 Matrix —— 二分
  • 原文地址:https://www.cnblogs.com/Comfortable/p/8412255.html
Copyright © 2011-2022 走看看