• 2017.7.6 C组总结


    NO.1

    题目描述:
    Mirko 最近发现了一个古老的游戏。这个游戏的屏幕有N列。在屏幕的底部,有个占M(M< N)列的船。在玩这个游戏的过程中,我们可以左右移动这条船,但是这条船必须时刻完整的在屏幕里面。这条船开始的时候是在最左边的。
    有一些苹果从这个屏幕的顶部掉下来,每个苹果会从屏幕N列中的某一列的顶部掉下来,垂直下落直到到达屏幕的底部。当前一个苹果掉落在底部以后,后一个苹果开始下落。
    一个苹果被船接到是这么定义的:这条船占有这个苹果掉下来的那一列。我们的目标是接到所有的苹果,在这种情况下,我们要求在所有苹果的掉落过程中,尽量减少船的移动总距离。

    思路:定义两个变量 l 和 r,表示船两端的位置
    从x掉下来苹果,如:①在船的上方,不用移动
    ②在船的左方,那么移动步数为l-x,l=x r=l+m-1
    ③在船的右手,那么移动步数为x-r, r=x l=r-m+1
    一直模拟就可以A

    代码:

    var  n,m,j,l,r,i,ans,x:longint;
    begin
      readln(n,m);
      readln(j);
      l:=1;
      r:=m;
      for i:=1 to j do
        begin
          readln(x);
          if r<x then
            begin
              ans:=x-r+ans;
              r:=x;
              l:=r-m+1;
            end;
          if l>x then
            begin
              ans:=l-x+ans;
              l:=x;
              r:=l+m-1;
            end;
        end;
      write(ans);
    end.

    NO.2

    题目描述:
    总所周知,我们住在一个N*N的方阵(正方形)里面。其中每个小格子中都有一个整数。为了离开这个方阵,我们必须找到最美丽的子方阵。
    如果我们定义A为某个方阵主对角线上的和,定义B为某个方阵副对角线上的和,那这个方阵的美丽值就是A-B。

    思路:前缀和
    设x[i,j]为到左上角的对角线,状态转移方程为x[i,j]=x[i-1,j-1]+a[i,j]
    设y[i,j]为到右上角的对角线,状态转移方程为y[i,j]=y[i-1,j+1]+a[i,j]
    然后用三重循环来枚举右下角的坐标和矩阵边长,那么这个矩阵的美丽值为(x[i,j]-x[i-k,j-k])-(y[i,j-k+1]-y[i-k,j+1])

    代码:

    uses math;
    var n,i,j,k,ans:longint;
        a,x,y:array[0..401,0..401]of longint;
    begin
      fillchar(x,sizeof(x),#0);
      fillchar(y,sizeof(y),#0);
      readln(n);
      for i:=1 to n do
        begin
          for j:=1 to n do begin read(a[i,j]); x[i,j]:=x[i-1,j-1]+a[i,j]; end;
          readln;
        end;
      for i:=1 to n do
        for j:=n downto 1 do
          y[i,j]:=y[i-1,j+1]+a[i,j];
       for i:=2 to n do
         for j:=2 to n do
           for k:=2 to min(i,j) do
             ans:=max(ans,(x[i,j]-x[i-k,j-k])-(y[i,j-k+1]-y[i-k,j+1]));
      write(ans);
    end.

    NO.3

    题目描述:
    在舞会上有N个男孩和N个女孩,每个人都量过了自己的身高。每个男孩只跟女孩跳舞,并且女孩也只跟男孩跳舞。每个人最多只有一个舞伴。男孩或者想和比自己高的女孩跳舞,或者想和比自己低的女孩跳舞,同样的,女孩也是或者想和比自己高的男孩跳舞,或者想和自己低的男孩跳舞
    你能决定最多有多少对能在一起跳舞么?

    思路:快排+暴力模拟
    首先将男生从大到小排序,女生从小到大排序
    然后在找出男生、女生正和负的分界点x1、x2(Tips:如果没找到就设为n+1)
    分两个循环枚举,其时间复杂度为O(n)
    ①定义l=1,来枚举女生
    循环i:1~x1-1
    如果b[i]

    var n,i,l,ans,x1,x2:longint;
        b,g:array[0..100001]of longint;
    
    procedure qsort(l,r:longint);
    var i,j,mid:longint;
    begin
      if l>=r then exit;
      i:=l; j:=r; mid:=b[(l+r) div 2];
      repeat
        while b[i]>mid do inc(i);
        while b[j]<mid do dec(j);
        if i<=j then
          begin
            b[0]:=b[i];
            b[i]:=b[j];
            b[j]:=b[0];
            inc(i);
            dec(j);
          end;
      until i>j;
      qsort(l,j);
      qsort(i,r);
    end;
    
    procedure qsort1(l,r:longint);
    var i,j,mid:longint;
    begin
      if l>=r then exit;
      i:=l; j:=r; mid:=g[(l+r) div 2];
      repeat
        while g[i]<mid do inc(i);
        while g[j]>mid do dec(j);
        if i<=j then
          begin
            g[0]:=g[i];
            g[i]:=g[j];
            g[j]:=g[0];
            inc(i);
            dec(j);
          end;
      until i>j;
      qsort1(l,j);
      qsort1(i,r);
    end;
    
    begin
      readln(n);
      for i:=1 to n do read(b[i]);
      readln;
      for i:=1 to n do read(g[i]);
      qsort(1,n);
      qsort1(1,n);
      for i:=1 to n do
        begin
          if (b[i]<0)and(x1=0) then x1:=i;
          if (g[i]>0)and(x2=0) then x2:=i;
          if (x1<>0)and(x2<>0) then break;
        end;
      if x1=0 then x1:=n+1; if x2=0 then x2:=n+1; 
      l:=1;
      for i:=1 to x1-1 do
        begin
          if l>x2 then break;
          if abs(b[i])<abs(g[l]) then begin inc(ans);inc(l); end;
        end;
      l:=x2;
      for i:=x1 to n do
        begin
          if l>n then break;
          if abs(b[i])>abs(g[l]) then begin inc(ans);inc(l); end;
        end;
      write(ans);
    end.

    NO.4

    题目描述:
    金明今天很开心,家里购置的新房就要领钥匙了,新房里有一间金明自己专用的很宽敞的房间。更让他高兴的是,妈妈昨天对他说:“你的房间需要购买哪些物品,怎么布置,你说了算,只要不超过N元钱就行”。今天一早,金明就开始做预算了,他把想买的物品分为两类:主件与附件,附件是从属于某个主件的,下表就是一些主件与附件的例子:

    主件 附件
    电脑 打印机,扫描仪
    书柜 图书
    书桌 台灯,文具

    如果要买归类为附件的物品,必须先买该附件所属的主件。每个主件可以有0个、1个或2个附件。附件不再有从属于自己的附件。金明想买的东西很多,肯定会超过妈妈限定的N元。于是,他把每件物品规定了一个重要度,分为5等:用整数1~5表示,第5等最重要。他还从因特网上查到了每件物品的价格(都是10元的整数倍)。他希望在不超过N元(可以等于N元)的前提下,使每件物品的价格与重要度的乘积的总和最大。
    设第j件物品的价格为v[j],重要度为w[j],共选中了k件物品,编号依次为j1,j2,……,jk,则所求的总和为:
    v[j1]w[j1]+v[j2]*w[j2]+ …+v[jk]*w[jk]。(其中为乘号)
    请你帮助金明设计一个满足要求的购物单。

    思路:DP大法
    设f[i,j]为取到第i个,用了j的价钱的最大价值
    如果为附件或买不起,则f[i,j]:=f[i-1,j];
    如果为主件,则有三种情况:
    ①只取主件,f[i,j]:=max(f[i-1,j],f[i-1,j-v[i]]+w[i]*v[i]);;
    ②取主件和附件一(要枚举的j>=主件的价钱和附件一的费用,而且要该主件有附件一), f[i,j]:=max(f[i,j],f[i-1,j-v[i]-v[fj[i,1]]]+w[i]*v[i]+w[fj[i,1]]*v[fj[i,1]]);;
    ③取主件和附件二(j>=主件和附件二的费用,而且该主件有附件二), f[i,j]:=max(f[i,j],f[i-1,j-v[i]-v[t2]]+w[i]*v[i]+w[t2]*v[t2]);
    ④取主件和附件一二(j>=主件和附件一二的费用,而且该主件有附件一和二),f[i,j]:=max(f[i,j],f[i-1,j-v[i]-v[t1]-v[t2]]+w[i]*v[i]+w[t1]*v[t1]+w[t2]*v[t2]);

    代码:

    uses math;
    var f:array[0..60,0..32000] of int64;
        fj:array[0..60,1..2] of longint;
        w,v,num,q:array[1..60] of longint;
        i,j,x,y,z,k,m,n,p,t1,t2:longint;sum:int64;
    begin
      assign(input,'budget.in');
      assign(output,'budget.out');
      reset(input);
      rewrite(output);
      readln(n,m);
      for i:=1 to m do
        begin
          readln(v[i],w[i],q[i]);
          if q[i]>0 then
            begin
              inc(num[q[i]]);
              fj[q[i],num[q[i]]]:=i;
            end;
        end;
      for i:=1 to m do
        for j:=0 to n do
          if (v[i]>j)or(q[i]>0) then f[i,j]:=f[i-1,j]
          else
            begin
              f[i,j]:=max(f[i-1,j],f[i-1,j-v[i]]+w[i]*v[i]);
              if num[i]>=1 then if j-v[i]-v[fj[i,1]]>=0 then
                  f[i,j]:=max(f[i,j],f[i-1,j-v[i]-v[fj[i,1]]]+w[i]*v[i]+w[fj[i,1]]*v[fj[i,1]]);
              if num[i]=2 then
                begin
                  t1:=fj[i,1];
                  t2:=fj[i,2];
                  if j-v[i]-v[t2]>=0 then f[i,j]:=max(f[i,j],f[i-1,j-v[i]-v[t2]]+w[i]*v[i]+w[t2]*v[t2]);
                  if j-v[i]-v[t1]-v[t2]>=0 then f[i,j]:=max(f[i,j],f[i-1,j-v[i]-v[t1]-v[t2]]+w[i]*v[i]+w[t1]*v[t1]+w[t2]*v[t2]);
                end;
            end;
      writeln(f[m,n]);
      close(input);
      close(output);
    end.
  • 相关阅读:
    codeforces 560 B. Gerald is into Art (模拟)
    导航控制器属性和基本使用
    多控制器和导航控制器简单介绍
    SQLite数据库框架--FMDB简单介绍
    数据库sqlite3的使用-ios中引用方法
    数据库sqlite3的使用-代码实例应用
    数据库sqlite3的使用-基本语法
    数据库sqlite3的使用-Navicat的安装
    如何制作.a静态库?合成多架构静态库?
    苹果Instruments/Shark性能调试工具概述
  • 原文地址:https://www.cnblogs.com/Comfortable/p/8412274.html
Copyright © 2020-2023  润新知