【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

相关文章

Vue3 的 shallowRef 和 shallowReactive:优化性能

大家对 Vue3 的 ref 和 reactive 都很熟悉,那么对 shallowRef 和 shallowReactive 是否了解呢? 在编程和数据结构中,“shallow”(浅层)通常指对数据结构的最外层进行操作,而不递归地处理其内部或嵌套的数据。这种处理方式关注的是数据结构的第一层属性或元素,而忽略更深层次的嵌套内容。 1. 浅层与深层的对比 1.1 浅层(Shallow) 定义

服务器集群同步时间手记

1.时间服务器配置(必须root用户) (1)检查ntp是否安装 [root@node1 桌面]# rpm -qa|grep ntpntp-4.2.6p5-10.el6.centos.x86_64fontpackages-filesystem-1.41-1.1.el6.noarchntpdate-4.2.6p5-10.el6.centos.x86_64 (2)修改ntp配置文件 [r

中文分词jieba库的使用与实景应用(一)

知识星球:https://articles.zsxq.com/id_fxvgc803qmr2.html 目录 一.定义: 精确模式(默认模式): 全模式: 搜索引擎模式: paddle 模式(基于深度学习的分词模式): 二 自定义词典 三.文本解析   调整词出现的频率 四. 关键词提取 A. 基于TF-IDF算法的关键词提取 B. 基于TextRank算法的关键词提取

使用SecondaryNameNode恢复NameNode的数据

1)需求: NameNode进程挂了并且存储的数据也丢失了,如何恢复NameNode 此种方式恢复的数据可能存在小部分数据的丢失。 2)故障模拟 (1)kill -9 NameNode进程 [lytfly@hadoop102 current]$ kill -9 19886 (2)删除NameNode存储的数据(/opt/module/hadoop-3.1.4/data/tmp/dfs/na

HDFS—存储优化(纠删码)

纠删码原理 HDFS 默认情况下,一个文件有3个副本,这样提高了数据的可靠性,但也带来了2倍的冗余开销。 Hadoop3.x 引入了纠删码,采用计算的方式,可以节省约50%左右的存储空间。 此种方式节约了空间,但是会增加 cpu 的计算。 纠删码策略是给具体一个路径设置。所有往此路径下存储的文件,都会执行此策略。 默认只开启对 RS-6-3-1024k

Hadoop数据压缩使用介绍

一、压缩原则 (1)运算密集型的Job,少用压缩 (2)IO密集型的Job,多用压缩 二、压缩算法比较 三、压缩位置选择 四、压缩参数配置 1)为了支持多种压缩/解压缩算法,Hadoop引入了编码/解码器 2)要在Hadoop中启用压缩,可以配置如下参数

Makefile简明使用教程

文章目录 规则makefile文件的基本语法:加在命令前的特殊符号:.PHONY伪目标: Makefilev1 直观写法v2 加上中间过程v3 伪目标v4 变量 make 选项-f-n-C Make 是一种流行的构建工具,常用于将源代码转换成可执行文件或者其他形式的输出文件(如库文件、文档等)。Make 可以自动化地执行编译、链接等一系列操作。 规则 makefile文件

使用opencv优化图片(画面变清晰)

文章目录 需求影响照片清晰度的因素 实现降噪测试代码 锐化空间锐化Unsharp Masking频率域锐化对比测试 对比度增强常用算法对比测试 需求 对图像进行优化,使其看起来更清晰,同时保持尺寸不变,通常涉及到图像处理技术如锐化、降噪、对比度增强等 影响照片清晰度的因素 影响照片清晰度的因素有很多,主要可以从以下几个方面来分析 1. 拍摄设备 相机传感器:相机传

hdu2241(二分+合并数组)

题意:判断是否存在a+b+c = x,a,b,c分别属于集合A,B,C 如果用暴力会超时,所以这里用到了数组合并,将b,c数组合并成d,d数组存的是b,c数组元素的和,然后对d数组进行二分就可以了 代码如下(附注释): #include<iostream>#include<algorithm>#include<cstring>#include<stack>#include<que

pdfmake生成pdf的使用

实际项目中有时会有根据填写的表单数据或者其他格式的数据,将数据自动填充到pdf文件中根据固定模板生成pdf文件的需求 文章目录 利用pdfmake生成pdf文件1.下载安装pdfmake第三方包2.封装生成pdf文件的共用配置3.生成pdf文件的文件模板内容4.调用方法生成pdf 利用pdfmake生成pdf文件 1.下载安装pdfmake第三方包 npm i pdfma