【CSP】2021-09-3 脉冲神经网络 使用滚动数组代替map优化时间+常数级优化

本文主要是介绍【CSP】2021-09-3 脉冲神经网络 使用滚动数组代替map优化时间+常数级优化,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

2021-09-3 脉冲神经网络 使用滚动数组代替map优化时间+常数级优化

首先说这题非常的恶心,算是一个垃圾题目,竟然卡的不是算法而是一些常数级优化,同样的算法可以拿到66分,而且同样的算法可以在acwing上过,但是csp的官方oj却有时候过有时候不过,很恶心,要是考试遇到了这种题目是不可能拿到100分的。

思路

这题的思路基本上所有人都能想到,和之前的第三题一样要建立索引。

首先我们解决这个题目一定是要遍历每个时刻,然后更新每个脉冲源和神经元的,然后可能会发出脉冲到突触(边)上,但是突触上脉冲的传播有时延,是在D个时间后,接收端才能接收到脉冲,所以这时候我们就要为每个神经元建立一个索引 用时间索引接受到脉冲的和(I[i][j] 表示i号神经元在j时刻接受到脉冲强度的总和),这样我们如果有脉冲到,可以直接加在对应的神经元的时间上,取的时候也可以直接取。

遇到的问题

  1. 使用double 做map的索引有问题

一开始没发现,用浮点数做索引会出现精度问题,就是同样是6.2 存储的时候有可能是6.19999999和6.20000001这样的然后判断索引的时候就取不到6.2索引对应的数据。后面改成int就好了

  1. 常数级优化

这题如果你是按照上边的思路写的,那么不出意外会只能拿到66分

在这里插入图片描述

会超时,因为题目时间限制是1s并且时间复杂度是 1 0 8 10^8 108所以我们需要一些常数级的优化(很恶心没见过卡这个的)。

  1. 将map换成二维数组

就是

struct neuron
{unordered_map<int, double> I;double v, u, a, b, c, d;int t;           // 表示neuron所处的时间
} nes[2001];         // 神经元

将里面的I提出出来

改成

double I[1005][1005];

这样就好了,并且由于时间是 1 0 5 10^5 105而神经元也有 1 0 3 10^3 103个这样就会导致超出空间限制

不知道为啥csp的oj报这个错误

在这里插入图片描述

然后使用滚动数组就好了

之后多提交几次就可以拿到时而83时而66的分数

在这里插入图片描述

  1. 其他的常数级优化

不使用万能头

// #include <bits/stdc++.h>
#include <iostream>
#include <cstring>
#include <vector>

使用 inline优化函数

inline int myrand(void)
{next1 = next1 * 1103515245 + 12345;return ((unsigned)(next1 / 65536) % 32768);
}

使用scanf printf 优化输入输出

    scanf("%d %d %d %d", &N, &S, &P, &T);scanf("%lf", &dt);printf("%.3f %.3f\n", min_v, max_v);printf("%d %d", min_times, max_times);

使用register优化循环

    for (register int i = 0; i < S; i++){struct link temp;int s;// cin >> s >> temp.t >> temp.w >> temp.D;scanf("%d %d %lf %d", &s, &temp.t, &temp.w, &temp.D);m[s].push_back(temp);mod = max(mod, temp.D + 1);// m[s][temp.t] = temp;}

然后就可以时而100分时而83分,但是acwing可以稳定拿到100分

在这里插入图片描述

完整代码

// #include <bits/stdc++.h>
#include <iostream>
#include <cstring>
#include <vector>using namespace std;
static unsigned long next1 = 1;
int N, S, P, T;
double dt;
struct neuron
{// unordered_map<int, double> I;// double I[2010];double v, u, a, b, c, d;int t;           // 表示neuron所处的时间
} nes[2001];         // 神经元
int out_times[2001]; // 发生脉冲的次数
int mod = 0;
double I[1005][1005];
struct link
{double w;int D;int t = -1;
};// 突触 注意第一个索引有可能大于等于N
// 如果大于等于N则为脉冲源
// unordered_map<int, vector<struct link>> m;
vector<struct link> m[2001];double r[2001]; // 脉冲源
/* RAND_MAX assumed to be 32767 */
inline int myrand(void)
{next1 = next1 * 1103515245 + 12345;return ((unsigned)(next1 / 65536) % 32768);
}signed main()
{// ios::sync_with_stdio(false);// cin.tie(0);// cout.tie(0);// cin >> N >> S >> P >> T;// cin >> dt;scanf("%d %d %d %d", &N, &S, &P, &T);scanf("%lf", &dt);int sum = 0;while (sum < N){int rn;double v, u, a, b, c, d;// cin >> rn >> v >> u >> a >> b >> c >> d;scanf("%d %lf %lf %lf %lf %lf %lf", &rn, &v, &u, &a, &b, &c, &d);for (register int i = 0; i < rn; i++){nes[sum + i].a = a, nes[sum + i].b = b, nes[sum + i].c = c, nes[sum + i].d = d;nes[sum + i].v = v, nes[sum + i].u = u;}sum += rn;}for (register int i = 0; i < P; i++){// cin >> r[i];scanf("%lf", &r[i]);}for (register int i = 0; i < S; i++){struct link temp;int s;// cin >> s >> temp.t >> temp.w >> temp.D;scanf("%d %d %lf %d", &s, &temp.t, &temp.w, &temp.D);m[s].push_back(temp);mod = max(mod, temp.D + 1);// m[s][temp.t] = temp;}int t = 0;while (t < T){t++;int t_tmp = t % mod;for (register int i = 0; i < P; i++) // 遍历脉冲源{// vector<struct link> temp = m[i + N];int rand = myrand();if (rand < r[i]){// for (int j = 0; j < N; j++)// {//     struct link item = m[i + N][j];//     if (item.t != -1)//         nes[item.t].I[t + item.D] += item.w;// }for (int j = 0; j < m[i + N].size(); j++){struct link item = m[i + N][j];I[(t_tmp + item.D) % mod][item.t] += item.w;// nes[item.t].I[t + item.D] += item.w;}}}for (register int i = 0; i < N; i++) //{nes[i].t = t;double v = nes[i].v, u = nes[i].u;nes[i].v = v + dt * (0.04 * v * v + 5 * v + 140 - u) + I[t_tmp][i];// nes[i].v = v + dt * (0.04 * v * v + 5 * v + 140 - u) + nes[i].I[t];// nes[i].I.erase(t);nes[i].u = u + dt * nes[i].a * (nes[i].b * v - u);if (nes[i].v >= 30){out_times[i]++;nes[i].v = nes[i].c;nes[i].u += nes[i].d;for (int j = 0; j < m[i].size(); j++){struct link item = m[i][j];I[(t_tmp + item.D) % mod][item.t] += item.w;// nes[item.t].I[t + item.D] += item.w;}}}memset(I[t_tmp], 0, sizeof I[t_tmp]);}double max_v = -1 * 1e8, min_v = 1e8;int max_times = -1, min_times = 1e5;for (register int i = 0; i < N; i++){max_v = max(nes[i].v, max_v);min_v = min(nes[i].v, min_v);max_times = max(out_times[i], max_times);min_times = min(out_times[i], min_times);}// cout << fixed << setprecision(3) << min_v << ' ' << max_v << endl;// cout << min_times << ' ' << max_times;printf("%.3f %.3f\n", min_v, max_v);printf("%d %d", min_times, max_times);return 0;
}

这篇关于【CSP】2021-09-3 脉冲神经网络 使用滚动数组代替map优化时间+常数级优化的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/822246

相关文章

Linux中压缩、网络传输与系统监控工具的使用完整指南

《Linux中压缩、网络传输与系统监控工具的使用完整指南》在Linux系统管理中,压缩与传输工具是数据备份和远程协作的桥梁,而系统监控工具则是保障服务器稳定运行的眼睛,下面小编就来和大家详细介绍一下它... 目录引言一、压缩与解压:数据存储与传输的优化核心1. zip/unzip:通用压缩格式的便捷操作2.

MySQL查询JSON数组字段包含特定字符串的方法

《MySQL查询JSON数组字段包含特定字符串的方法》在MySQL数据库中,当某个字段存储的是JSON数组,需要查询数组中包含特定字符串的记录时传统的LIKE语句无法直接使用,下面小编就为大家介绍两种... 目录问题背景解决方案对比1. 精确匹配方案(推荐)2. 模糊匹配方案参数化查询示例使用场景建议性能优

关于集合与数组转换实现方法

《关于集合与数组转换实现方法》:本文主要介绍关于集合与数组转换实现方法,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录1、Arrays.asList()1.1、方法作用1.2、内部实现1.3、修改元素的影响1.4、注意事项2、list.toArray()2.1、方

使用Python实现可恢复式多线程下载器

《使用Python实现可恢复式多线程下载器》在数字时代,大文件下载已成为日常操作,本文将手把手教你用Python打造专业级下载器,实现断点续传,多线程加速,速度限制等功能,感兴趣的小伙伴可以了解下... 目录一、智能续传:从崩溃边缘抢救进度二、多线程加速:榨干网络带宽三、速度控制:做网络的好邻居四、终端交互

Python中注释使用方法举例详解

《Python中注释使用方法举例详解》在Python编程语言中注释是必不可少的一部分,它有助于提高代码的可读性和维护性,:本文主要介绍Python中注释使用方法的相关资料,需要的朋友可以参考下... 目录一、前言二、什么是注释?示例:三、单行注释语法:以 China编程# 开头,后面的内容为注释内容示例:示例:四

Go语言数据库编程GORM 的基本使用详解

《Go语言数据库编程GORM的基本使用详解》GORM是Go语言流行的ORM框架,封装database/sql,支持自动迁移、关联、事务等,提供CRUD、条件查询、钩子函数、日志等功能,简化数据库操作... 目录一、安装与初始化1. 安装 GORM 及数据库驱动2. 建立数据库连接二、定义模型结构体三、自动迁

MyBatisPlus如何优化千万级数据的CRUD

《MyBatisPlus如何优化千万级数据的CRUD》最近负责的一个项目,数据库表量级破千万,每次执行CRUD都像走钢丝,稍有不慎就引起数据库报警,本文就结合这个项目的实战经验,聊聊MyBatisPl... 目录背景一、MyBATis Plus 简介二、千万级数据的挑战三、优化 CRUD 的关键策略1. 查

ModelMapper基本使用和常见场景示例详解

《ModelMapper基本使用和常见场景示例详解》ModelMapper是Java对象映射库,支持自动映射、自定义规则、集合转换及高级配置(如匹配策略、转换器),可集成SpringBoot,减少样板... 目录1. 添加依赖2. 基本用法示例:简单对象映射3. 自定义映射规则4. 集合映射5. 高级配置匹

Spring 框架之Springfox使用详解

《Spring框架之Springfox使用详解》Springfox是Spring框架的API文档工具,集成Swagger规范,自动生成文档并支持多语言/版本,模块化设计便于扩展,但存在版本兼容性、性... 目录核心功能工作原理模块化设计使用示例注意事项优缺点优点缺点总结适用场景建议总结Springfox 是

嵌入式数据库SQLite 3配置使用讲解

《嵌入式数据库SQLite3配置使用讲解》本文强调嵌入式项目中SQLite3数据库的重要性,因其零配置、轻量级、跨平台及事务处理特性,可保障数据溯源与责任明确,详细讲解安装配置、基础语法及SQLit... 目录0、惨痛教训1、SQLite3环境配置(1)、下载安装SQLite库(2)、解压下载的文件(3)、