201709 CSP认证

201709-1 打酱油
15ms
哪个便宜先买哪个套餐

#include<bits/stdc++.h>
using namespace std;
int main()
{
    int n; cin >> n;
    // 买5瓶: 50rmb  == > 50 / 7 = 7.14
    // 买3瓶: 30rmb  == > 30 / 4 = 7.5
    // 买1瓶: 10rmb
    int ans = 0;

    ans += (n / 50) * 7;
    n = n % 50;

    ans += (n / 30) * 4;
    n = n % 30;

    ans += (n / 10);

    cout << ans;
    return 0;
}

2 公共钥匙盒
15 ms
写了我一个半小时,虽然写出来了但是成就感大打折扣…
而且区区第二题我已经用了优先队列和map,感觉是不是写的太复杂了…

#include<bits/stdc++.h>
using namespace std;
typedef pair<int, int> PII;
const int N = 1010;
int box[N];
map<int, int> pos;  //记录编号为i 的钥匙此时的pos[i]

priority_queue<PII, vector<PII>, greater<PII> > taken_time;
priority_queue<PII, vector<PII>, greater<PII> > return_time;
priority_queue<int, vector<int>, greater<int> > taken_key;  //用来记录编号最小的位置
int main()
{
    int n, k; 
    cin >> n >> k;
    for(int i = 1;i <= n; i ++)  {
        box[i] = i;  
        pos[i] = i;
    }
    PII t;

    while(k --){
        int w, s, c; 
        cin >> w >> s >> c;
        t = {s, w};
        taken_time.push(t);  //按照开始取钥匙时间排序

        t = {s + c, w};
        return_time.push(t);  //按照开始放回钥匙时间排序
    }
 
    
    int time1, time2;
    time1 = taken_time.top().first;
    time2 = return_time.top().first;

    while(!taken_time.empty() && !return_time.empty()) {
        
        while(time1 < time2 && !taken_time.empty() && !return_time.empty()) {
            //在t.first 时刻取走编号为t.second 的钥匙
            t = taken_time.top(); taken_time.pop();

            //取走钥匙
            taken_key.push(pos[t.second]);  //放入取走钥匙的位置
            if(!taken_time.empty())
                time1 = taken_time.top().first;
        }

        //time1 >= time2, 此时开始放回钥匙
        while(time1 >= time2 && !return_time.empty() && !taken_time.empty()) {
            // 在t.first 时刻放回编号为t.second 的钥匙
            t = return_time.top(); return_time.pop();
           
            //放回钥匙
            int loc = taken_key.top();  //取出当前最靠左的空位
            taken_key.pop();

            box[loc] = t.second;
            pos[t.second] = loc;
            if(!return_time.empty())
                time2 = return_time.top().first;
        }
    }
    
    //只可能是全放入了
    while(!return_time.empty()) {
        t = return_time.top(); return_time.pop();
        int loc = taken_key.top();  //取出当前最靠左的空位
        taken_key.pop();

        box[loc] = t.second;  //放回钥匙
    }

    for(int i = 1;i <= n;i ++) cout << box[i] << " ";
    cout << endl;
    return 0;
}

201709-3 JSON查询
老规矩…我老牛拉磨一次性肯定写不了三题,待补充…

2023/11/09 18点19分
找了几篇博客,最后选了一篇初始看上去代码比较简单,结构没有很复杂的,虽然光看代码去理解就看了我半个多小时咳咳咳。其他的很多都涉及到自定义结构体,我自己本人不是特别喜欢用而且没有经常在第三题看到。
参考链接:JSON查询 (100分) 【文本处理】

在这篇博客中,博主采用了有限状态自动机的思想来编写程序,也即出现某种语法成分后进入到某一种状态中,在相应的状态下做相应的处理。

代码中有一个全局变量state用来标识这种状态
state = 0为初始状态,也即进入json模式的入口
state = 1为录入key字段状态,此时期望找到格式正确的key
state = 2为录入value字段状态,此时key字段已经完整正确录入,正在录入当前保存的key字段的value值

自己按照那个逻辑结构纯手敲了一遍,加了自己理解的注释
好牛啊,感觉就是我想不出的感觉,知识的味道…

#include<bits/stdc++.h>
using namespace std;
string key;    //单次只处理一个键值对
//比起Markdown有所不同的是,那边只需要处理数据,遇到什么判定类型直接输出就好了
//而本题的key和value是配对的,而且有不在一行的可能,因此需要记录数据

int state; //用来记录状态;有限状态机模型,什么样的状态对应什么样的操作
// 0为初始状态
// 1为录入key状态
// 2为录入value状态
map<string, string> json;

void handle(string line)
{
    for(int i = 0;i < line.size();i ++){
        if(line[i] == '{') {
            if(state == 0) {
                //初始状态, 按理来说只会进入一次,接下来每次进到这个判断语句都是因为有多级结构
                key = "";   //初始化key字段
                state = 1;  //进入json状态, 默认在key字段部分
            }
            else {
                //只要不是初始状态, 此时一定进入了多级结构
                json[key] = "OBJECT";
                state = 1;   //接下来会读入多个多级的key和value,此时修改为录入key字段模式,注意不能有key = "",此时要保留key用作前缀字段
            }
        }

        else if(line[i] == '}') {
            //要么是所有的结束要么是一个多级结构的结束
            int j = key.size() - 1;
            while(key[j] != '.' && j >= 0) j --;

            if(j > 0) {
                //一个多级结构的结束
                key = key.substr(0, j);  //进行key字段的一个回退
            }
            else key = "";  //?
        }

        if(line[i] == ':') state = 2;  //进入value录入环节

        else if(line[i] == ',') state = 1;  //进入新一个key字段录入环节


        else if(line[i] == '"') {
            string text = "";
            i ++;

            //获取有效字段(可能为key也可能为value)
            for(;i < line.size();i ++){
                if(line[i] == '"') break;  //有效字段获取结束
                if(line[i] == '\\') {
                    i ++;
                    text += line[i];  //跳过转义字符
                }
                else text += line[i];
            }

            if(state == 1) {  //录入key
                //根据key字段的形式判断是否为多级结构
                if(key == "")  key = text;
                else  key = key + '.' + text;
                state = 2;
            }

            else if(state == 2) {
                json[key] = "STRING " + text;

                //录完value字段对key做处理
                int j = key.size() - 1;
                while(key[j] != '.' && j >= 0) j --;

                if(j > 0) key = key.substr(0, j); //回退一级属性
                else key = "";  //一个崭新的一级key字段,置空,等待再次进入有效字段的获取

                state = 1;
            }
        }
    }
}

int main()
{
    int n, m;
    cin >> n >> m;
    state = 0;  //设为初始状态
    string line;
    getline(cin, line);
    while(n --){
        getline(cin, line);
        handle(line);
    }

    string query;
    while(m --) {
        getline(cin, query);
        if(json.count(query))  cout << json[query] << endl;
        else puts("NOTEXIST");
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值