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


T1 最少充电次数

题面


数据范围

思路

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

其实看到问题很容易产生贪心想法,选择充电效率较高的充电站以在相同的时间内获得更多电量。那其他维度相同的状态中是不是应选择剩余电量更多的状态?想到这点,重新定义状态 dp[n][rtime][ans]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×1e4×512≈2.5e9512\times1e4\times512\approx2.5e9512×1e4×512≈2.5e9,提交上去只能过前面两个点。
然后,开始想办法借助STL进行优化(感觉CCF比赛我总是靠乱搞STL出奇迹)。
用数组存储状态,你只能按下标进行递推,但这会冗余考虑很多不可能的状态,从不可能的状态递推怎么也无法到达可能的状态。于是乎我改用 map<node,int>stat[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行驶至ifor (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;}// ansfor (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];
#endifvoid 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 arrmemset(dp, -1, sizeof dp);dp[1][maxtime][0] = initbat;    // 初始化
#elsestat[1][{maxtime, 0}] = initbat;
#endifint s = 1;for (int i = 0; i < n; i++) {// 从i-1行驶至i
#ifdef arrfor (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]);}}
#elsefor (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 Debugcout << "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 arrmemset(dp[s], -1, sizeof dp[s]);
#elsestat[s].clear();
#endifs ^= 1;// 充电for (int t = 0; t <= tlimit[i]; t++) {// 状态转移
#ifdef arrfor (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]);}}}
#elsefor (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 Debugcout << "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 arrmemset(dp[s], -1, sizeof dp[s]);
#elsestat[s].clear();
#endifs ^= 1;}// ans
#ifdef arrfor (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;}}}
#elsefor (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 310 2 2 5
3 8
1 1
3 2*/

2022CCSP T1最少充电次数相关推荐

  1. HDU 1257 - 最少拦截系统 ( LIS / 贪心 )

    题目 现在有一种拦截系统,第一发拦截可以是任意高度,但是之后的拦截高度不能比上次高.为了拦截下所有的炮弹,最少需要准备几套拦截系统? 思路 可能是语文没学好吧,一开始被题意卡了一下.(而且题目连数据范 ...

  2. “最少惊讶”和可变默认参数

    长时间修改Python的任何人都被以下问题咬伤(或弄成碎片): def foo(a=[]):a.append(5)return a Python新手希望此函数始终返回仅包含一个元素的列表: [5] . ...

  3. 20181102 T1 相遇

    在一场奇怪的梦里,小 Y 来到了一个神奇的国度.这个国度可以用一根数 轴表示,小 Y 在 N 处,而小 Y 想吃的美食在 K 处. 小 Y 有两种方式移动,一种叫做步行,一种叫做瞬移.对于每次步行操作 ...

  4. 谈谈Dictionarylt;T1,T2gt;和Listlt;Tgt;的问题 [转]

    引子: 事情的起因我已经记不清了,但是事情的根本原因在于,我们要遍历一个集合,是用字典来存储还是用数组链表来存储. 1.       把基本概念说清 对List<T>的阐述,我在http: ...

  5. LeetCode 1665. 完成所有任务的最少初始能量

    1665. 完成所有任务的最少初始能量 [贪心+排序]ti [ai, mi] 如果按照顺序t0,t1那么t01: e > m0 e - a0 > m1             e > ...

  6. 数据中心等级T1,T2,T3,T4,T5区别,科普数据中心等级知识

    谈的数据中心等级,很多人对数据中心等级划分并不了解.今天给大家普及一下数据中心等级划分. 了解更好IDC,运维,互联网商业请上我个人博客网站 https://www.serverceping.com/ ...

  7. 力扣276 周赛 2139. 得到目标值的最少行动次数

    2139. 得到目标值的最少行动次数 题目描述: 你正在玩一个整数游戏.从整数 1 开始,期望得到整数 target . 在一次行动中,你可以做下述两种操作之一: 递增,将当前整数的值加 1(即, x ...

  8. 牛客 换钱的最少货币数

    题目链接:https://www.nowcoder.com/practice/4e05294fc5aa4d4fa8eacef2e606e5a8?tpId=101&tqId=33080& ...

  9. c语言随机生成凸多边形源代码,求能够包含随机产生的点的边数最少的凸多边形...

    求能够包含随机产生的点的边数最少的凸多边形 各位大虾,帮忙看看这个程序有什么错误好吗?????? #include "stdio.h" #include "math.h& ...

最新文章

  1. 【NLP】词嵌入基础和Word2vec
  2. spd耗材管理流程图_国药器械山东公司助力济宁医学院附属医院SPD项目成功启动...
  3. 剑指offer之分行从上到下之字行打印二叉树
  4. OpenShift 4 - 如何删除Terminating状态的项目
  5. [转]c# winform tcp connect timeout 连接超时设置
  6. 使用JSON实现分页
  7. java程卫琴_43名基层工会干部在“机关开放日”走进安徽省总工会参观并座谈
  8. java mdb连接_[Java]如何连接一个带密码的mdb文件?
  9. YOLO学习笔记4——YOLOV2详解+论文解读
  10. python做积分_python曲线积分
  11. python 基础-如何调用函数
  12. drawableTop,button图片显示在文字上面,文字不显示的问题
  13. 腾讯校招软件测试工程师题库
  14. 火影七代目的青鸟誓言
  15. 禅与摩托车维修艺术 摘选
  16. 使用 hugo 快速开发博客网页
  17. Pandas学习笔记(一)
  18. 2022年5月20号对数据库的操作课时二:
  19. react学习—高阶组件HOC
  20. 数据库编程——简单教程

热门文章

  1. Ga结合模拟退火算法
  2. Flume-ng的原理和使用
  3. 对C语言中与运算符与或运算符||的探讨
  4. AD学习笔记--构建51最小系统板
  5. NLP经典论文:Attention、Self-Attention、Multi-Head Attention、Transformer 笔记
  6. 【✨十五天搞定电工基础】一阶电路的暂态分析
  7. html判断qq微信浏览器打开,JS判断QQ内置浏览器和QQ浏览器
  8. 学习自旋电子学的笔记01:微磁模拟软件OOMMF的教程(中文版)10-15章
  9. 解决【不能初始化 Photoshop,因为暂存盘已满】的问题
  10. 你有没有听说过拓扑绝缘体?它有没有可能替代硅?-道合顺大数据Infinigo