脉冲神经网络

题目链接

模拟题最难的就是读懂题,理清思路,但基本上不需要什么算法就可以拿到很大一部分分数(40-100不等)。

问题描述

脉冲神经网络模型由神经元、脉冲源、突触三种部分组成,突触连接脉冲源和神经元,同时连接神经元和神经元,它用于传播脉冲,但会有一定的时延。当$r>\text{myrand()}$时,脉冲源会通过突触传播给所有与它连接的神经元;神经元如果接收到信号,也会通过计算判断是否传递该信号到它的邻居节点上。

由于有一定的延迟,我们需要一个二维数组,一维是时间,二维是每个点接收的信号强度,来记录一段时间内的各神经元接收到的信息。

以下是60分代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
#include <bits/stdc++.h>
using namespace std;
static unsigned long _next = 1;
const int INF = 1e8;
/* RAND_MAX assumed to be 32767 */
int myrand() {
_next = _next * 1103515245 + 12345;
return((unsigned)(_next/65536) % 32768);
}

const int N = 1001;
double I[1024][N]; // 脉冲
int n, s, p, t;
double dt;

/* 神经元信息 */
double v[N<<1], u[N<<1], a[N<<1], b[N<<1], c[N<<1], d[N<<1];
int r[N<<1];
int h[N<<1], D[N<<1], idx, e[N<<1], ne[N<<1];
double w[N<<1];
int cnt[N<<1];
void add(int aa, int bb, double ww, int DD) {
D[idx] = DD, w[idx] = ww, e[idx] = bb, ne[idx] = h[aa], h[aa] = idx++;
}

int main() {
scanf("%d%d%d%d", &n, &s, &p, &t);
scanf("%lf", &dt);
memset(h, -1, sizeof h);
int sum = 0;
int iidx = 0, max_d = 0;
while(true) {
int rn;
double vv, uu, aa, bb, cc, dd;
scanf("%d%lf%lf%lf%lf%lf%lf", &rn, &vv, &uu, &aa, &bb, &cc, &dd);
sum += rn;
for(int i = 0; i < rn; ++i) {
v[iidx] = vv, u[iidx] = uu, a[iidx] = aa, b[iidx] = bb, c[iidx] = cc, d[iidx] = dd;
iidx++;
}
if(sum == n) break;
}
// 脉冲源信息读入
for(int i = n; i < n + p; ++i) scanf("%d", &r[i]);

// 每条边的信息
for(int i = 0; i < s; ++i) {
int ss, tt, DD;
double ww;
scanf("%d%d%lf%d", &ss, &tt, &ww, &DD);
max_d = max(max_d, DD+1);
add(ss, tt, ww, DD);
}
// 至此,完成读入...

for(int i = 0; i < t; ++i) {
int tt = i % max_d;
for(int j = n; j < n + p; ++j) {
if(r[j] > myrand()) {
for(int k = h[j]; k != -1; k = ne[k]) {
I[(tt+D[k]) % max_d][e[k]] += w[k];
}
cnt[j]++;
}
}
for(int j = 0; j < n; ++j) {
double vv = v[j], uu = u[j];
v[j] = vv + dt * (0.04 * vv * vv + 5 * vv + 140 - uu) + I[tt][j];
u[j] = uu + dt * a[j] * (b[j] * vv - uu);
if(v[j] >= 30) {
// 发送一个脉冲
for(int k = h[j]; k != -1; k = ne[k]) {
I[(tt+D[k]) % max_d][e[k]] += w[k];
}
v[j] = c[j], u[j] += d[j];
cnt[j]++;
}
}
memset(I[tt], 0, sizeof I[tt]);
}
double minv = INF, maxv = -INF;
int maxc = -INF, minc = INF;
for(int i = 0; i < n; ++i) {
minv = min(minv, v[i]);
maxv = max(maxv, v[i]);
maxc = max(maxc, cnt[i]);
minc = min(minc, cnt[i]);
}
printf("%lf %lf\n%d %d", minv, maxv, minc, maxc);
return 0;
}