Codeforces Round 946 (Div. 3)

A.手机桌面 

З手机桌面- A - Codeforcesicon-default.png?t=N7T8https://codeforces.com/contest/1974/problem/A

解析题目

这个问题是一个应用图标布局的最优化问题,主要是要最小化使用的桌面屏幕数量。每个屏幕是5行3列的网格,共有15个单元格。我们有两种图标:1x1大小的图标和2x2大小的图标。题目要求得出放置x块1×1和y块2×2的最少屏幕个数。

分析思路

我们首先可以考虑2×2的方块,显然,一个屏幕只能放得下2个2×2的图标,如上图所示

但是 我们又可以在一个屏幕布满2×2的图标中放置1×1的图标。所以我们可以优先考虑2×2的情况

然后根据屏幕中剩余的空间来分配1×1的图标,如果x是大于剩余空间的,那么我们就需要新增屏幕的个数来装下多余的图标

这里有个向上取整的小技巧,通常使用 被除数 + (除数 - 1)/ 除数

对于2×2的图标

  • 目标:确保在计算放置2x2图标所需屏幕数时,所有图标都能被包含。由于每个屏幕可以放置最多两个2x2图标,当有奇数个2x2图标时,单纯的除法会向下取整,可能导致计算出的屏幕数不足
  • 方法:加1是在这种情况下最简单的修正方法。对于每2个图标需要一个屏幕的计算,通过y+1可以确保当你有奇数个图标时,这个额外的图标也能得到计算。例如,对于5个2x2图标,(5 + 1) / 2 = 3 正确反映了需要3个屏幕(而不是 5 / 2 = 2.5 向下取整为2个屏幕)。

对于1×1的图标

  • 目标:确保在计算额外需要多少屏幕来放置1x1图标时,每个屏幕的容量被最大化利用,且所有图标都能被放置。
  • 方法:由于每个屏幕可以放置15个1x1图标,加14确保了在计算额外屏幕时,即使有1到14个多余的1x1图标,也会额外考虑一个屏幕。这避免了由于整数除法的向下取整而导致的屏幕数不足。例如,如果有16个1x1图标,16 + 14 = 30,然后 30 / 15 = 2 正确计算出需要2个屏幕。

 代码

#include <iostream>
using namespace std;

int main() {
    int t;
    cin >> t;
    while (t--) {
        int x, y;
        cin >> x >> y;

        // 计算至少需要多少屏幕来放置所有2x2图标,向上取整
        int screens_for_2x2 = (y + 1) / 2;  // 每个屏幕最多放2个2x2图标

        // 计算当前屏幕中剩余的单元格数
        int remaining = 15 * screens_for_2x2 - 4 * y;
        //cout<<remaining<<'\n';

        // 判断1x1图标是否可以完全放入剩余的空间
        if (x > remaining) {
            x -= remaining;  // 移除已占用的空间
            // 新屏幕需要为剩下的1x1图标提供空间
            int additional_screens = (x + 14) / 15;  // 每个屏幕可以放15个1x1图标,保证向上取整
            //cout<<additional_screens<<'\n';
            screens_for_2x2 += additional_screens;
        }

        // 输出每个测试案例所需的最小屏幕数
        cout << screens_for_2x2 << endl;
    }
    return 0;
}

B. 对称编码

任务 - B - Codeforcesicon-default.png?t=N7T8https://codeforces.com/contest/1974/problem/B

解析题目

题目的意思是给你一个对原始字符编码的结果的字符串s,要求你通过对称方式来获得原始字符串s

分析思路

既然题目有了对原字符串编码后的字符串b,那么我们需要通过构造一个辅助字符串r来把字符串b中每个字符换成字符串r中的对称字符,从而得到原始字符串s。对称关系如图所示:

 首先就是构造辅助字符串r

题目中对辅助字符串r是这样描述的:它建立了一个新的助手线r,它由字符串的所有不同字母组成s按字母顺序书写;

那么我们就可以考虑用桶来记录每个字符出现的次数,只要出现过,就让他加在辅助字符串r中;

通过字符串r来找到对应的替换关系

构造一个字符数组用于解码

对称式的映射关系怎么表示呢?

我们知道的是,第一个要替换成倒数第一个,第二个要替换成倒数第二个。由此类推,我们会发现,位于字符串r中的第i个位置的字符串要替换成r_len-i-1位置的字符。那么我们通过这种规律来构造字符数组。

构造原始字符串s

我们通过上一步构造的字符数组来构造原始字符串s

例如:考虑b字符串当中的c字符,通过映射关系,字符数组里面储存的就是字符s,那么显然,只需要遍历字符串b,通过每一次访问当前字符串b中的字符对应的字符数组中的元素,来确定原始字符串的每一个字符。

代码

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

int main() {
    int t;
    cin >> t;
    while (t--) {
        int n;
        cin >> n;
        string b;
        cin >> b;

        // 清零字符计数数组
        vector<int> count(26, 0);

        // 计数b中的字符
        for (char ch : b) {
            count[ch - 'a']++;
        }

        // 构建辅助字符串r
        string r = "";
        for (int i = 0; i < 26; i++) {
            if (count[i] > 0) {
                r += char(i + 'a');
            }
        }

        // 创建一个字符数组用于解码
        char decode[122]; 
        int r_len = r.length();
        for (int i = 0; i < r_len; i++) {
            decode[r[i]] = r[r_len - i - 1];//让r[i]对应的解码是r的len - i -1位置处的字符
        }

        // 构造原始字符串s
        string s = "";
        for (char ch : b) {
            s += decode[ch];
        }

        
        cout << s << endl;
    }
    return 0;
}

  • 21
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值