2022CCSP T1最少充电次数

news2024/10/5 19:20:15

记录第一次CCSP竞赛。一共3题,只做出第一题,用时3h30m(累),ac了开心地吃了个午饭。然而饭饱之后,大脑完全提不起神看着题面昏昏欲睡。第二题是虚拟内存,超级大模拟,刚好这个学期学os,但是翘了太多课完全看不懂,自己看ppt学了一点多级页表,但是1v0,1v1啥的想不明白怎么对应呀。第三题跟数据库系统有关,高性能 RDF 图查询系统,给了一个代码框架,稍微看了看,代码十分规范,应用了很多C++继承、虚基类等等特性,然后按要求实现一些函数方法,不会。下面主要记录第一题的思路。


T1 最少充电次数

题面

在这里插入图片描述
数据范围
在这里插入图片描述

思路

DP,有电量、充电时间两个维度约束,一开始我定义的状态是 d p [ n ] [ r t i m e ] [ r b a t ] dp[n][rtime][rbat] dp[n][rtime][rbat],维度的含义是当前站点、剩余充电时间和剩余电量,存储相应的最小充电次数,但是更新该状态数组会发现剩余电量这一维度是 ( 1 < < 30 ) ≈ 1 e 9 (1<<30)\approx1e9 (1<<30)1e9,这肯定T飞。

其实看到问题很容易产生贪心想法,选择充电效率较高的充电站以在相同的时间内获得更多电量。那其他维度相同的状态中是不是应选择剩余电量更多的状态?想到这点,重新定义状态 d p [ n ] [ r t i m e ] [ a n s ] dp[n][rtime][ans] dp[n][rtime][ans],调换一下,最后一维表示充电次数,数组存储最大剩余电量。
递推分为行驶和充电,由于当前状态仅仅和前面一个状态有关,将第一维度赋为2,滚动数组以压缩空间。
① 行驶至下一个充电站:

dp[s ^ 1][j][k] = max(dp[s ^ 1][j][k], dp[s][j][k] - d[i + 1] + d[i]);

② 充电:

dp[s ^ 1][j][k] = dp[s][j][k];	// t==0
dp[s ^ 1][j - t][k + 1] = max(dp[s ^ 1][j - t][k + 1], dp[s][j][k] + t * cspeed[i]);	// t!=0

优化

仔细算一下复杂度,充电站数×总最大充电时间×充电次数, 512 × 1 e 4 × 512 ≈ 2.5 e 9 512\times1e4\times512\approx2.5e9 512×1e4×5122.5e9,提交上去只能过前面两个点。
然后,开始想办法借助STL进行优化(感觉CCF比赛我总是靠乱搞STL出奇迹)。
用数组存储状态,你只能按下标进行递推,但这会冗余考虑很多不可能的状态,从不可能的状态递推怎么也无法到达可能的状态。于是乎我改用 m a p < n o d e , i n t > s t a t [ 2 ] map<node, int> stat[2] map<node,int>stat[2],其中 node 的定义为

struct node {
    int rtime, cnt;
    bool operator < (const node &d) const {
        return cnt < d.cnt;
    }
};

这个结构仅仅存储有效状态,因而我们也只会从有效状态开始递推,避免冗余。

AC代码

在这里插入图片描述
太菜了,一发AC高兴得不得来了。。。

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

int d[550], tlimit[550], cspeed[550];

struct node {
    int rtime, cnt;
    bool operator < (const node &d) const {
        return cnt < d.cnt;
    }
};
// 只对有效状态进行转移
map<node, int> stat[2];

void solve() {
    int totdis, n, maxtime, initbat;
    cin >> totdis >> n >> maxtime >> initbat;
    d[0] = 0;
    for (int i = 1; i <= n; i++) cin >> d[i];
    for (int i = 0; i < n; i++) cin >> tlimit[i];
    for (int i = 0; i < n; i++) cin >> cspeed[i];

    stat[1][{maxtime, 0}] = initbat;

    int s = 1;
    for (int i = 0; i < n; i++) {
        // 从i-1行驶至i
        for (const auto &[x, r] : stat[s]) {
            if (stat[s][x] - d[i + 1] + d[i] >= 0) {
                stat[s ^ 1][x] = stat[s][x] - d[i + 1] + d[i];
            }
        }

        stat[s].clear();
        s ^= 1;

        // 充电
        for (int t = 0; t <= tlimit[i]; t++) {
            // 状态转移
            for (const auto &[x, r] : stat[s]) {
                if (x.rtime < t) continue;
                if (t) {
                    int tmp = 0;
                    if (stat[s ^ 1][{x.rtime - t, x.cnt + 1}]) {
                        tmp = stat[s ^ 1][{x.rtime - t, x.cnt + 1}];
                    }
                    stat[s ^ 1][{x.rtime - t, x.cnt + 1}] = max(tmp, r + t * cspeed[i]);
                }
                else { stat[s ^ 1][{x.rtime, x.cnt}] = r; }
            }
        }

        stat[s].clear();
        s ^= 1;
    }

    // ans
    for (const auto &[x, r] : stat[s]) {
        if (r >= totdis - d[n]) {
            cout << x.cnt << '\n';
            return;
        }
    }
    { cout << "-1\n"; }
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    cout.tie(nullptr);
    solve();
    return 0;
}

提交代码

仅仅作为个人记录。

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
//#define Debug
//#define arr
// 选择充电不一定会充至时间上限
// dp[n][rtime][rbat]:充电次数,(当前所在充电站、剩余充电时间、剩余电量)
// 512*(1e4)*(1<<30)
// 到达终点最少充电次数
/*
 * dp[i][rtime][rbat]=dp[i-1][rtime][rbat+d[i]-d[i-1]]
 * dp[i][rtime-t][rbat+t*cspeed[i]]=dp[i][rtime][rbat]+1,t<=tlimit[i]
 */

// 分组背包
// 每组取物品个数=每个服务站充电时间
// 充电速度不同->选择剩余电量最多的状态
// dp[n][rtime][ans]

/*
 * dp[n][rtime][i]=max(dp[n][rtime+t][i-1]+t*cspeed[i])
 */

int d[550], tlimit[550], cspeed[550];
#ifdef arr
int dp[2][10010][550];   // 该状态下最大剩余电量
#else
struct node {
    int rtime, cnt;
    bool operator < (const node &d) const {
        return cnt < d.cnt;
    }
};
// 只对有效状态进行转移
map<node, int> stat[2];
#endif

void solve() {
    int totdis, n, maxtime, initbat;
    cin >> totdis >> n >> maxtime >> initbat;
    d[0] = 0;
    for (int i = 1; i <= n; i++) cin >> d[i];
    for (int i = 0; i < n; i++) cin >> tlimit[i];
    for (int i = 0; i < n; i++) cin >> cspeed[i];
#ifdef arr
    memset(dp, -1, sizeof dp);
    dp[1][maxtime][0] = initbat;    // 初始化
#else
    stat[1][{maxtime, 0}] = initbat;
#endif

    int s = 1;
    for (int i = 0; i < n; i++) {
        // 从i-1行驶至i
#ifdef arr
        for (int j = maxtime; j >= 0; j--) {
            for (int k = 0; k <= i; k++) {
                dp[s ^ 1][j][k] = max(dp[s ^ 1][j][k], dp[s][j][k] - d[i + 1] + d[i]);
            }
        }
#else
        for (const auto &[x, r] : stat[s]) {
            if (stat[s][x] - d[i + 1] + d[i] >= 0) {
                stat[s ^ 1][x] = stat[s][x] - d[i + 1] + d[i];
            }
        }
#endif

#ifdef Debug
        cout << "arrive: " << i << '\n';
//        for (int j = maxtime; j >= 0; j--) {
//            cout << "rest time: " << j << '\n';
//            for (int k = 0; k <= i && k <= n; k++) {
//                cout << "(" << k << "," << dp[s ^ 1][j][k] << ") ";
//            }
//            cout << '\n';
//        }   cout << '\n';
        for (const auto &x : stat[s ^ 1]) {
            cout << x.rtime << ' ' << x.cnt << ' ' << x.rbat << '\n';
        }   cout << '\n';
#endif
#ifdef arr
        memset(dp[s], -1, sizeof dp[s]);
#else
        stat[s].clear();
#endif
        s ^= 1;
        // 充电
        for (int t = 0; t <= tlimit[i]; t++) {
            // 状态转移
#ifdef arr
            for (int j = maxtime; j >= 0; j--) {
                if (j < t) break;
                for (int k = 0; k <= i && k <= n; k++) {
                    if (!t) {
                        dp[s ^ 1][j][k] = dp[s][j][k];
                    }
                    else {
                        if (dp[s][j][k] < 0) continue;
                        dp[s ^ 1][j - t][k + 1] = max(dp[s ^ 1][j - t][k + 1], dp[s][j][k] + t * cspeed[i]);
                    }
                }
            }
#else
            for (const auto &[x, r] : stat[s]) {
                if (x.rtime < t) continue;
                if (t) {
                    int tmp = 0;
                    if (stat[s ^ 1][{x.rtime - t, x.cnt + 1}]) {
                        tmp = stat[s ^ 1][{x.rtime - t, x.cnt + 1}];
                    }
                    stat[s ^ 1][{x.rtime - t, x.cnt + 1}] = max(tmp, r + t * cspeed[i]);
                }
                else { stat[s ^ 1][{x.rtime, x.cnt}] = r; }
            }
#endif
        }


#ifdef Debug
        cout << "charge: " << i << '\n';
//        for (int j = maxtime; j >= 0; j--) {
//            cout << "rest time: " << j << '\n';
//            for (int k = 0; k <= (i + 1) && k <= n; k++) {
//                cout << "(" << k << "," << dp[s ^ 1][j][k] << ") ";
//            }
//            cout << '\n';
//        }   cout << '\n';
        for (const auto &x : stat[s ^ 1]) {
            cout << x.rtime << ' ' << x.cnt << ' ' << x.rbat << '\n';
        }   cout << '\n';
#endif
//        memset(dp[s], -1, sizeof dp[s]);

#ifdef arr
        memset(dp[s], -1, sizeof dp[s]);
#else
        stat[s].clear();
#endif
        s ^= 1;
    }

    // ans
#ifdef arr
    for (int k = 0; k <= n; k++) {
        for (int j = maxtime; j >= 0; j--) {
            if (dp[s][j][k] >= totdis - d[n]) {
                cout << k << '\n';
                return;
            }
        }
    }
#else
    for (const auto &[x, r] : stat[s]) {
        if (r >= totdis - d[n]) {
            cout << x.cnt << '\n';
            return;
        }
    }
#endif
    { cout << "-1\n"; }
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    cout.tie(nullptr);
    solve();
    return 0;
}

/*
10 2 2 2
3 8
1 1
2 3

10 2 2 5
3 8
1 1
3 2
 */

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/81197.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

2023最新SSM计算机毕业设计选题大全(附源码+LW)之java流浪动物救助网站a1wsz

毕业设计也不需要做多高端的程序&#xff0c;毕业设计对于大多数同学来说&#xff0c;为什么感觉到难&#xff0c;最重要的一个原因&#xff0c;那就是理论课到实践课的转变&#xff0c;很多人一下不适应&#xff0c;本能开始拒绝&#xff0c;如果是一个考试&#xff0c;大家都…

ITU、MCC和MNC介绍以及China运营商对照表

相关概念 ITU 国际电信联盟是联合国负责信息通信技术&#xff08;ICT&#xff09;事务的专门机构。 国际电联成立于1865年&#xff0c;为了促进国际上通信网络的互联互通。他们进行全球无线电频谱和卫星轨道的划分&#xff0c;制定技术标准以确保实现网络和技术的无缝互连&…

【Docker】30条Docker常用命令图文举例总结

本期目录1. 帮助启动类命令2. 镜像命令2.1 列出镜像2.2 搜索远程库镜像2.3 拉取镜像2.4 查看所占空间2.5 删除镜像2.6 面试题3. 容器命令3.1 新建启动容器1&#xff09;启动交互式容器3.2 列出当前所有正在运行的容器3.3 退出容器3.4 启动已停止的容器3.5 重启容器3.6 停止容器…

第六章 映射:Mappings

文章目录1、Mapping 简介1.1 mapping 是啥&#xff1f;1.2 如何查看索引映射2、自动映射&#xff1a;dynamic mapping2.1 自动类型推断规则2.2 mapping 的使用禁忌2.3 自动映射器的意义是什么&#xff1f;3、手动映射&#xff1a;Explicit mapping3.1 创建索引的 mapping3.2 修…

电子产品量产工具项目开发中遇到的问题(更新......)

1、找不到tslib.h库的头文件 这是因为找不到tslib库的头文件。 确定工具链中头文件、库文件目录&#xff0c;对于 IMX6ULL &#xff0c;命令如下 echo main(){}| arm-linux-gnueabihf-gcc -E -v -找到了编译器arm-linux-gnueabihf的include和lib文件夹 /usr/local/arm/gcc-l…

AT155 高压绝缘电阻测试仪 都有哪些功能?

、 高压绝缘电阻测试仪是—款手持式仪表主要用来测量交流&#xff0f;直流电压、 电阻、 短路蜂鸣测试和 绝缘电阻测量。 式高压绝缘电阻测试仪具有4个量程用千绝缘电阻、 AC/DC电压、 电阻和短路蜂鸣测试。 设计达到以下安全标准 &#xff0e;绝缘测试量程O.lMn to 60Gn。…

机器学习 决策树基础 ID3、C4.5、CART

文章目录参考决策树指标基尼系数基础公式公式理解引入划分后的公式划分后公式的理解信息熵、信息增益如何理解信息熵两种指标的对比划分策略ID3定义举例计算各属性的信息增益选取最优属性作划分对子节点作递归划分生成结果ID3的缺点C4.5信息增益率优化缺点CARTCART相较于前两者…

Windows下使用C语言创建定时器并周期和网络调试助手通信

在Windows C下采用timeSetEvent函数来设置定时器 关于timeSetEvent的函数原型及注释如下所示&#xff1a; MMRESULT timeSetEvent(UINT uDelay, // 定时事件的触发周期&#xff0c;单位为毫秒UINT uResolution, // 定时事件的精度&#xff0c;单位…

161-183-mysql-高级篇-事务-锁-mvcc

116-mysql-事务篇-锁&#xff1a; 推荐网站 mysql学习网站&#xff1a;https://www.bilibili.com/video/BV1iq4y1u7vj?p109&vd_source39a1ba1654411bc9ab90f6f2926600b7 mysql&#xff1a;https://dev.mysql.com/doc/refman/8.0/en/ 算法&#xff1a;https://www.cs.us…

我看世界杯——来自一个“假”球迷视角

世界杯还有一个星期就要结束了&#xff0c;说实话&#xff0c;我之前是一场球都没有&#xff0c;对足球知道也甚少&#xff0c;妥妥一个假球迷了。这次世界杯感觉离自己特别近&#xff0c;身边的很多朋友都在看&#xff0c;也不乏赌球的小伙伴&#xff0c;自己的感悟也比较深&a…

电机定子模态的空间特征

对于电机定子模态而言&#xff0c;通常不是按传统的阶次顺序&#xff08;按频率从小到大&#xff09;来描述它们&#xff0c;而是按空间节点数的顺序来描述&#xff0c;这在很大程度上是因为受激励的电磁力波的振型的影响。 1、传统模态阶次表示方式 传统模态阶次的顺序都是按…

安卓期末大作业——个人简历APP源码和设计报告

Android课程需求文档 设计题目&#xff1a; 个人简历APP 学生姓名&#xff1a; 学号&#xff1a; 1&#xff0e;Smart.apk功能设计说明 Android真机运行进入该app。背景音乐服务播放正常&#xff0c;并设置可通过右上角按钮关闭musicservice&#xff1b; 1通过viewpager实…

Jenkins+SonarQube 代码质量检测详解

一、SonarQube 概述 1、SonarQube 简介 Sonar Qube是一个开源的代码分析平台,支持Java、Python、PHP、JavaScript、CSS等25种以上的语言,可以检测出重复代码、代码漏洞、代码规范和安全性漏洞的问题。 Sonar Qube通过插件机制,Sonar可以集成不同的测试工具,代码分析工具…

【JavaWeb开发-Servlet】将项目打包部署在本地

Servlet与JSP进阶十&#xff1a;Web应用程序打包与发布&#xff08;war包&#xff09;_小枯林的博客-CSDN博客_servlet项目如何打成war包本篇博客主要内容是&#xff1a; ●如何使用Eclipse打war包&#xff1b; ●打好的war包如何发布&#xff1b;访问演示&#xff1b; ●解决u…

如何使用ChatGPT辅助AI绘画?

如何使用ChatGPT辅助AI绘画&#xff1f; AI自动化内容生成&#xff08;AIGC&#xff09;是一种利用人工智能技术生成新内容的方法。它可以快速、自动、准确地从大量原始数据中生成新内容&#xff0c;大大提高了内容创作效率。AIGC 使用机器学习算法&#xff0c;自动识别文本特…

【MySQL】触发器

目录 概述 操作-创建触发器 操作-NEW与OLD 其他操作 注意事项 概述 介绍 触发器&#xff0c;就是一种特殊的存储过程。触发器和存储过程一样是一个能够完成特定功能、存储在数据 库服务器上的SQL片段&#xff0c;但是触发器无需调用&#xff0c;当对数据库表中的数据执…

微信小程序|前端技术主要框架分析

1.框架 微信提供了一套自己的用于开发小程序的前端框架,和目前主流的前端框架相比,其既有类似的地方,也有特殊的地方。 特殊的地方在于其只能在微信小程序开发工具内使用,并做了相对严格的使用和配置限制,开发者必须按照其规定的用法来使用。一些外部的框架和插件在小程…

apis-day7综合案例

apis-day7综合案例-小兔鲜案例注册 需求①&#xff1a; 发送验证码 用户点击之后&#xff0c;显示 05秒后重新获取 时间到了&#xff0c;自动改为 重新获取 需求②&#xff1a; 用户名验证&#xff08;注意封装函数 verifyxxx&#xff09; 正则 /1{6,10}$/ 如果不符合要求…

非零基础自学Golang 第1章 走进Go 1.1 Go编程语言概述 1.1.3 使用Go 语言的项目

非零基础自学Golang 文章目录非零基础自学Golang第1章 走进Go1.1 Go编程语言概述1.1.3 使用Go 语言的项目第1章 走进Go 1.1 Go编程语言概述 1.1.3 使用Go 语言的项目 Go语言在2009年首次公开发布后受到越来越多的开发者的关注&#xff0c;Go语言社区不断壮大&#xff0c;开源…

【深度学习】李宏毅2021/2022春深度学习课程笔记 - Deep Learning Task Tips

文章目录一、深度学习步骤回顾二、常规指导三、训练过程中Loss很大3.1 原因1&#xff1a;模型过于简单3.2 原因2&#xff1a;优化得不好3.3 原因1 or 原因2 &#xff1f;四、训练过程Loss小。测试过程Loss大4.1 原因1&#xff1a;过拟合 Overfitting4.2 原因2&#xff1a;Misma…