[算法题] Codefun2000 6.9日模拟赛

242 阅读5分钟

www.codefun2000.com 是一个收集各种笔试题目,供大家学习交流,体会笔试难度的OJ网站。

题目链接

第一题

塔子哥最近沉迷于设计一个二维平面音游。在我们所给的例子里,假设有24个方块,分为水平8个和垂直3个(如下表格所示) 。当玩家点击一个亮起的方块时,它周围的所有方块都会高亮。为了实现这个互动功能,塔子哥提出了一个方块组的概念:一个方块的方块组是指在上下左右方向上紧挨着的所有方块和它自己。而且垂直方向上的方块是首尾相连的,但水平方向上的方块是首尾不连的。比如,在48个方块中,方块0的方块组是“16 8 1 0”,方块10的方块组是“2 9 18 11 10”,方块23的方块组是“15 22 7 23”。如下图所示,为了方便理解,我们把最后一行方块复制一份到第一行,表示上下相连:

1617181920212223
01234567
89101112131415
1617181920212223

塔子哥想要当玩家点击某个方块时,这个方块的整个方块组都会亮起。为了实现这个互动功能,他想让你设计一个程序,它能实时得到某个方块的方块组。

输入描述

第一行输入为3个正整数 H , VH , V (1H,V2561≤H,V≤256)和 MM (1M<H×V1 \leq M < H×V ), H ,VH ,V 为方块盘的水平个数和垂直个数;

接下来 MM 行,每一行输入一个方块的 IDID ,方格 IDID 从00开始,不超过 H×V1H \times V - 1 如:

8 3 1
12

输出描述

输出对应的方格组,方格组内 IDID 以空格分隔,IDID从上方起始,逆时针排列,输入的方格 IDID 放最后,如上例子对应的输出结果为: “4 11 20 13 12”

样例1

样例输入

12 4 1
21

输出

9 20 33 22 21
样例2

样例输入

16 4 2
0
21

样例输出

48 16 1 0
5 20 37 22 21

思路

十分简单的模拟题,但需要注意边界的处理。另外需要注意的是在本题中,如果V<2V<2是有重复输出的,但本题不需要去除这个重复输出。

code

#include <bits/stdc++.h>
using namespace std;

int main() {
    ios::sync_with_stdio(false);
    cin.tie(0);

    int H, V, M;
    cin >> H >> V >> M;

    for(int i = 0; i < M; ++i) {
        int id;
        cin >> id;
        
        int row = id / H;
        int col = id % H;

        // up
        if(row >= 1) {
            cout << (row - 1) * H + col << " ";
        }
        else{
        // 不需要考虑V <= 2时重复输出的情况,输出下面的方块id与此相同
        // else if (V > 2) { 
            cout << (V - 1) * H + col << " ";
        }

        // left
        if(col >= 1) {
            cout << id - 1 << " ";
        }

        // down
        if(row < V-1) {
            cout << (row + 1) * H + col << " ";
        }
        else {
        // else if(V > 2) {
            cout << col << " ";
        }

        // right
        if(col < H - 1) {
            cout << id + 1 << " ";
        }

        // self
        cout << id << endl;
    }
    
    return 0;
}

第二题

题目描述

塔子哥接到一个新课题,监测一整条河流的水质。

目前塔子哥选择了一条河流进行水质监测,长度为 N 公里。经过专业人员勘察,河流沿线有 K 个候选地点适合安装水质监测站,每个监测站可以覆盖的长度为半径 R 公里,单个监测站建设成本为 M。

假设塔子哥知道的河流是一条直线,请计算最少需要多少经费建设水质监测站才能完成对整条河流(也就是直线上的每一个实数点)的水质监测。

输入描述

输入第一行包含三个整数 N ,R ,M .(1N30001≤N≤3000,10R20010≤R≤200,1M100001≤M≤10000) 输入第二行包含 K 个整数a1,a2,...,aKa_1, a_2,..., a_K,表示在高铁沿线的第a1,a2,...,aKa_1, a_2,..., a_K公里的地点可以建设基站.(1KN,0aiN1 \leq K \leq N, 0 \leq a_i \leq N)

输出描述

输出一个整数,表示最少花费的经费,如果所有候选地点均建设了基站还是无法覆盖则输出 "-1" 。

样例1

样例输入

100 20 114514
10 30 50

样例输出

-1
样例2

样例输入

80 50 114514
0 20 40 60

样例输出

114514

思路

由于每个检测站能够覆盖的范围是相同的,因此本题可以使用贪心算法,从前位置往后依次遍历所有候选,找到能满足当前要求的最远的位置,并更新要求。对所谓“要求”解释如下: 若[0, last]已经能够被已有的监测站覆盖,其中last[0,N]last \in [0, N],则在下一个位置监测站的覆盖范围的左侧覆盖范围的边界pos_left需要小于等于last,即boundaryleft=posRlastboundary_{left} = pos - R \leq last

另外,本题需要注意:
1.需要先对原始输入进行升序排序;
2.在计算最终答案时涉及到了乘法,最好使用1ll来避免溢出,虽然在本题的测试用例中没有会溢出的。

code

#include <bits/stdc++.h>
using namespace std;

int main() {
    ios::sync_with_stdio(false);
    cin.tie(0);

    int N, R, M;
    int K = 0;
    vector<int> vec;
    cin >> N >> R >> M;

    int a;
    while (cin >> a) {
        vec.push_back(a);
        ++K;
    }    

    sort(vec.begin(),vec.end()); 
    
    int last = 0; // 已选择好位置的检测站能够覆盖范围的右边界
    int cnt = 0;
    for(int i = 0; i < K; ++i) {
        // 如果本位置建设无法满足要求,
        // 即所有候选位置中没有一个组合能覆盖整条河流,
        // 退出循环,输出-1
        if(vec[i]-R > last) {
            break;
        }

        // 本位置不是最后一个候选位置,
        // 且后一个候选位置不能满足要求
        if(i < K-1 && vec[i+1]-R > last) {
            last = vec[i] + R;
            cnt++;
        }
        
        // 当前建立的监测站已经能够覆盖
        // 整条河流,退出循环
        if(last >= N) {
            break;
        }
        
        // 当前位置是最后一个候选位置
        if(i == K-1) {            
            // 更新
            last = vec[i] + R;
            cnt++;
        }
    }

    // 选择好位置的监测站的覆盖范围的右边界小于河流长度
    // 输出-1
    if(last < N) {
        cout << -1 << endl;
    }
    else {
        // cout << 1ll * cnt * M << endl; // 更好
        cout << cnt * M << endl; 
    }

    return 0;
}

第三题

题目描述

塔子哥在一个 m×nm\times n大小的崎岖山地上进行跑步锻炼。这个场地由一系列的上坡、下坡组成,场地各点位的高度值记录于二位数组 hh 中,由相邻位置到达对应点位的减速值记录于二维数组 oo中。

已知塔子哥初始速度为 11 ,当他从高度为 h1ℎ1 的位置跑到高度为 h2ℎ2 、减速值为 o2o2 的相邻位置(可从上下左右四个方向)时,速度变化值为 h1h2o2h_1 - h_2 - o_2( 大于 00 为加速 ,小于 00 为减速)。速度不会为 00 或者负值。

请问塔子哥到达哪些点位时速度依旧维持为 11 ?请你求出这些位置的个数是多少。

输入描述

输入第一行为场地大小 m,n1  m  100,1  n 100m,n(1 ≤ m ≤ 100, 1 ≤ n ≤ 100)

输入第二行为选手初始位置 输入第三行为场地每个点位的高度值h[i][j]h[i][j],场地高度的范围为 [0,100][0,100]
输入第四行为每个点位的减速值o[i][j]o[i][j],减速值的范围在 [0,100] [0,100]

输出描述:

输出速度为 11 的位置的个数

样例1

输入

2,2
1,1
5,0 0,6
0,6 7,0

输出

1

解释:

第一行为场地大小为 2∗2; 第二行为塔子哥的初始位置坐标; 第三行分别代表 h[0][0]=5;h[0][1]=0;h[1][0]=0;h[1][1]=6ℎ[0][0]=5;ℎ[0][1]=0;ℎ[1][0]=0;ℎ[1][1]=6 第四行分别代表 o[0][0]=0;o[0][1]=6;o[1][0]=7;o[1][1]=0o[0][0]=0;o[0][1]=6;o[1][0]=7;o[1][1]=0 塔子哥从坐标[1][1]的位置出发,此为位置高度为 6, 减速值为 0 。 选手到达[0,1]处位置恰好为 1;速度的变化值为 0,初始速度为 1 ,即到达[0,1]处位置时,速度恰好为 1

样例2

输入

2,2
0,0
0,0 0,0
0,0 0,0

输出

3

解释:

场地大小 2∗2,选手从坐标 [0,0] 的位置出发,此位置高度为 0,减速值为 0。选手到达[0,1],[1,0] , [1,1]三处位置时,速度恰好为1。

思路

本题是图论相关的题目,有段时间没做了图论了,先去复习一下,本题有待更新。

注意输入需要处理‘,’号。

code