今日写题记录2026-5-19

写题写题,每天不刷,手感都没。。。

引用:洛谷P1109学生分组

## 题目描述

有 n组学生,给出初始时每组中的学生个数,再给出每组学生人数的上界 R和下界 L (L <=R),每次你可以在某组中选出一个学生把他安排到另外一组中,问最少要多少次才可以使 N 组学生的人数都在 [L,R]中。

## 输入格式

第一行一个整数 n,表示学生组数;

第二行 n 个整数,表示每组的学生个数;

第三行两个整数 L,R,表示下界和上界。

## 输出格式

一个数,表示最少的交换次数,如果不能满足题目条件输出 -1。

## 输入输出样例 #1

### 输入 #1
2
10 20
10 15

### 输出 #1
5

## 说明/提示

### 数据范围

对于全部数据,保证 1<=n<=50。

这个题看那个算法标签的时候是贪心了,其实贪心的思维其实更重要,我就认为贪心是要多少刷题的,有时候在写题总可能无形中用了贪心,这个题,我们先来探究啥时候输出-1了,我们就极端点来说,如果我输出的每组学生都是L,R的倍数就是加和可以整除的时候,要是再大一点点,或小一点点,就不可能满足条件了,所以当加和sum/n>R或者sum/n<L的时候,你怎么移也不可能了,那这一类题就大概这样写了:

#include <bits/stdc++.h>
using namespace std;
int main(){
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int n;
    cin>>n;
    int sum=0;
    vector<int> a(n+1);
    for(int i=1;i<=n;i++){
        cin>>a[i];
        sum+=a[i];
    }
    int L,R;
    cin>>L>>R;
    if(sum<L*n||sum>R*n){
        cout<<"-1"<<endl;
        return 0;
    }
    int need=0,out=0;
    for(int i=1;i<=n;i++){
        if(a[i]>R) out+=a[i]-R;//实际上就是记录多出来的和
        if(a[i]<L) need+=L-a[i];//实际上就是记录缺少的和
    }
    cout<<max(out,need)<<endl;//那我们发现多可以补少的,当补不完的时候,就需要我们去移动了。
    //就是说如果out>need的时候,我们可以视为移了need次后还要补out-need次,那么我们只要移动need次就行了。
    // 如果out<need的时候,我们可以视为移了out次后还要补need-out次,那么我们只要移动out次就行了。
    // 所以,综上我们只要移动max(out,need)次就行了。
}

引用:牛客新生赛的一道题

题目描述    明年就要考研了,我给自己制定了学习科目, 但是我该怎么合理的安排我的学习时才能让一天学习到的内容最多呢? 输入描述: 第一行输入学习科目数:n 之后连续输入n行,每行包括两个数据:科目开始时间和结束时间

注意:
 n=0表示输入结束,不做处理 
 输出描述: 输出所能完整学习到的最大科目数

输入

6
8 12
6 11
14 15
16 18
15 20
19 22
0

输出 

4

备注: 时间输入为整点,例如:1表示1点,13表示下午一点

这个题题目很短,一开始我确实看懵了,题目啥意思啊???,后面仔细看了样例,才明白我们要统计的是没冲突的时间段,就是说我先对第二个时间排序,选第一个时间段的的第二个最小结束时间作为一个参考对象,然后看后面的开始时间是否晚与结束时间,没有就是不冲突的,不冲突我们就count++,当然选开始时间来参考的话,就不可行了,因为开始不等于结束,如果开始早结束晚,我们没有办法判断是否冲突的,所以可以用二维数组来写,或者更简单点,要不哈希表?就是C++里的map,或者Java里的TreeMap,都会自动排序,比数组再排序就方便多了,那么代码如下:

#include <bits/stdc++.h>
using namespace std;
int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int n;
    while (cin >> n && n != 0){
        // key: 结束时间  value: 开始时间
        map<int, int> mp;//把map放在while循环里面,这样每次循环都会重新初始化map
        for (int i = 0; i < n; i++){
            int a, b;
            cin >> a >> b;
            mp[b] = a;
        }
        int last = -1;
        int count = 0;
        // 遍历 map(自动按结束时间从小到大)自带排序
        for (auto &p : mp){
            int end = p.first;
            int start = p.second;
            if (start >= last){// 如果当前时间段开始时间大于等于上一次结束时间,则说明可以加入
                count++;
                last = end;// 更新结束时间
            }
        }
        cout << count << endl;
    }
    return 0;
}

下面就是我觉得很有意思的题目:

引用:PTA L1-064 估值一亿的AI核心代码

以上图片来自新浪微博。

本题要求你实现一个稍微更值钱一点的 AI 英文问答程序,规则是:

  • 无论用户说什么,首先把对方说的话在一行中原样打印出来;
  • 消除原文中多余空格:把相邻单词间的多个空格换成 1 个空格,把行首尾的空格全部删掉,把标点符号前面的空格删掉;
  • 把原文中所有大写英文字母变成小写,除了 I
  • 把原文中所有独立的 can youcould you 对应地换成 I canI could—— 这里“独立”是指被空格或标点符号分隔开的单词;
  • 把原文中所有独立的 I 和 me 换成 you
  • 把原文中所有的问号 ? 换成惊叹号 !
  • 在一行中输出替换后的句子作为 AI 的回答。

输入格式:

输入首先在第一行给出不超过 10 的正整数 N,随后 N 行,每行给出一句不超过 1000 个字符的、以回车结尾的用户的对话,对话为非空字符串,仅包括字母、数字、空格、可见的半角标点符号。

输出格式:

按题面要求输出,每个 AI 的回答前要加上 AI: 和一个空格。

输入样例:

6
Hello ?
 Good to chat   with you
can   you speak Chinese?
Really?
Could you show me 5
What Is this prime? I,don 't know

输出样例:

Hello ?
AI: hello!
 Good to chat   with you
AI: good to chat with you
can   you speak Chinese?
AI: I can speak chinese!
Really?
AI: really!
Could you show me 5
AI: I could show you 5
What Is this prime? I,don 't know
AI: what Is this prime! you,don't know

这个题确实很有意思,不过写起来就有点复杂了,所以建议用Java的正则表达式写:

import java.io.*;
public class Main {
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
        int n = Integer.parseInt(br.readLine().trim());
        String str;
        while(n-- > 0) {
            str = br.readLine();
            bw.write(str);
            bw.newLine();
            // 只有字母 I 保持大写,其他字母全部转小写
            StringBuilder sb = new StringBuilder();
            for(char c : str.toCharArray()) {
                // 如果是大写字母
                if(c >= 'A' && c <= 'Z')
                    // 如果是 I 不变,其他大写字母转小写
                    sb.append(c == 'I' ? 'I' : Character.toLowerCase(c));
                else
                    // 非大写字母直接保留
                    sb.append(c);
            }
            String s = sb.toString();
            // 2. 格式规范化(正则)
            // 去掉多余空格,标点前不保留空格
            // 单引号前面的空格删掉
            s = s.replaceAll("\\s+'", "'");
            // 标点符号前面的空格删掉
            s = s.replaceAll("\\s+([,.?!;:])", "$1");
            // 多个连续空格变成一个空格,并去掉首尾空格
            s = s.replaceAll("\\s+", " ").trim();
            // 3. 关键词替换(核心逻辑)
            // 顺序绝对不能乱!!
            // could you 临时替换成 #1
            s = s.replaceAll("\\bcould you\\b", "#1");
            // can you 临时替换成 #2
            s = s.replaceAll("\\bcan you\\b", "#2");
            // 独立单词 I 替换成 you
            s = s.replaceAll("\\bI\\b", "you");
            // 独立单词 me 替换成 you
            s = s.replaceAll("\\bme\\b", "you");
            // 还原 #1 → I could
            s = s.replace("#1", "I could");
            // 还原 #2 → I can
            s = s.replace("#2", "I can");
            // 4. 问号 ? 全部变成感叹号 !
            s = s.replace('?', '!');
            // 输出AI回答
            bw.write("AI: " + s);
            bw.newLine();
        }
        bw.flush();
        bw.close();
        br.close();
    }
}
正则代码作用(中文解释)
\\s+'匹配单引号前面的所有空格,并删除这些空格
\\s+([,.?!;:])匹配标点前面的所有空格,删除空格,只保留标点
\\s+匹配连续多个空格,合并成一个空格
\\bcould you\\b匹配独立完整单词:could you
\\bcan you\\b匹配独立完整单词:can you
\\bI\\b匹配独立完整单词:I
\\bme\\b匹配独立完整单词:me

实际上这个题我还没有完全写出来,因为非正则的写法一直过不了所有样列,所以我询问了AI学习了里面的正则来写这个题所以这个题明日我还会再写,把他写对为止,其实我个人不喜欢记正则表达式的,多数想手写,所以在手写的角度下我是失败的,格式错误,答案错误等等,明日再写

总结一下:今天的写题其实多写了几个贪心题,之前我对贪心不是那样的熟悉,所以今后还要多写这类,可以说我在这方面还是入门的,最后再看到PTA这个题的时候,就写了恒久,最后学了一下正则表达式,事实上它还是很使用的,比如说我们去多个空格时候在不知道空格个数的情况下,只能标记,那么我们用正则的话,replace("//s+","")就可以了,还有在判断字符串里有没有汉字的时候可能只能有ASCII来看,手写麻烦,那么正则就可以一行解决了,就是:

正则Java 写法作用
[\u4E00-\u9FA5][\\u4E00-\\u9FA5]匹配单个汉字
.*.*匹配任意 0 个或多个字符
.*[\\u4E00-\\u9FA5].*整串是否包含汉字

这个在登录系统里就很好用了,判断用户名有没有汉字等等,明日再改非正则的,写代码嘛,就是要有写不出来不肯罢休的劲,加油!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值