赞
踩
由于我有些看不懂这个题目,所以我是先找的他人的博客理解了一下题目。
这个博客写得很详细的(66分),有助于理解题目。 CSP 202109-3 脉冲神经网络(详解)_刘学.的博客-CSDN博客
所以我这里主要就是记录一下这道题啦,想到如何优化到100分,再更新。
66分
- #include <iostream>
- #include <iomanip>
-
- using namespace std;
-
- // 神经元结构
- struct neuron {
- int ID, times;
- double prev, preu; //v, u; // 由于后续这个v、u用处不大,我就没写上了
- double a, b, c, d;
- };
-
- struct pluse {
- int ID;
- long long int r;
- };
-
- struct synapse {
- int outID, inID, D;
- double w;
- };
-
- neuron neurons[1001];
- pluse pluses[1001];
- synapse synapses[1001];
-
- void InputData(int N, int P, int S) {
- for (int id = 0; id < N;) {
- int RN;
- double v, u, a, b, c, d;
- cin>>RN>>v>>u>>a>>b>>c>>d;
- for (int j = 0; j < RN; ++j, ++id) {
- neurons[id].times = 0;
- neurons[id].prev = v;
- neurons[id].preu = u;
- neurons[id].ID = id;
- neurons[id].a = a;
- neurons[id].b = b;
- neurons[id].c = c;
- neurons[id].d = d;
- }
- }
- for (int i = 0; i < P; ++i) {
- long long int r;
- cin>>r;
- pluses[i].ID = N + i;
- pluses[i].r = r;
- }
- for (int i = 0; i < S; ++i) {
- cin>>synapses[i].outID>>synapses[i].inID>>synapses[i].w>>synapses[i].D;
- }
- }
-
-
- static unsigned long Next = 1;
- /* RAND_MAX assumed to be 32767 */
- int myrand(void) {
- Next = Next * 1103515245 + 12345;
- return((unsigned)(Next/65536) % 32768);
- }
-
-
-
- int main() {
- int N, S, P, T;
- double deltaT;
- cin>>N>>S>>P>>T;
- cin>>deltaT;
-
- InputData(N, P, S);
-
- // 记录每个时刻的 IK !!!关键点 !!!
- double IK[1001][2001] = {0}; // int IK[1001][100101];
-
- for (int t = 1; t <= T; ++t) { // 每个时刻
- for (int i = 0; i < P; ++i) { // 每个脉冲源
- if (myrand() < pluses[i].r) { // 当 r > myrand() 时发放脉冲信号
- for (int j = 0; j < S; ++j) { // 每个突触
- if (synapses[j].outID == i + N) {
- IK[synapses[j].inID][t + synapses[j].D] += synapses[j].w;
- }
- }
- }
- }
- }
-
- // 更新每个时刻的神经元
- for (int t = 1; t <= T; ++t) { // 每个时刻
- for (int i = 0; i < N; ++i) { // 每个神经元
- double ik = IK[i][t];
- double prev = neurons[i].prev, preu = neurons[i].preu;
- double v = prev + deltaT * (0.04 * prev * prev + 5 * prev + 140 - preu) + ik, // !!!0.04 not 0.004!!!
- u = preu + deltaT * neurons[i].a * (neurons[i].b * prev - preu);
-
- if (v >= 30) { // 神经元发放脉冲
- for (int j = 0; j < S; ++j) { // 对于每个突触
- if (synapses[j].outID == i) {
- IK[synapses[j].inID][t + synapses[j].D] += synapses[j].w; // += synapses[j].w; not synapses[synapses[j].inID].w;
- }
- }
- v = neurons[i].c;
- u = neurons[i].d + u;
- ++neurons[i].times;
- }
- neurons[i].prev = v;
- neurons[i].preu = u;
- }
- }
-
- // 找出最后的答案
- double minVV = neurons[0].prev, maxVV = neurons[0].prev;
- int minTimes = neurons[0].times, maxTimes = neurons[0].times;
- for (int i = 1; i < N; ++i) {
- minVV = min(minVV, neurons[i].prev);
- maxVV = max(maxVV, neurons[i].prev);
- minTimes = min(minTimes, neurons[i].times);
- maxTimes = max(maxTimes, neurons[i].times);
- }
-
- cout<<fixed<<setprecision(3)<<minVV<<" "<<fixed<<setprecision(3)<<maxVV<<endl<<minTimes<<" "<<maxTimes<< endl;
-
- return 0;
- }
-------------------------------------------- 更新 ----------------------------------------------
我的代码改得就差将大佬的代码复制粘贴了,可它还是超时超时66分。呜呜。
贴上 100分 的大佬代码的链接 CSP认证202109T3-脉冲神经网络(优化)_nth2000的博客-CSDN博客 参考参考, 方便以后复习吧。
把 66 分的也给贴上,以后再看问题在哪里了吧:
- /* 66 */
- #include <iostream>
- #include <iomanip>
- #include <map>
- #include <vector>
- #include <fstream>
-
- using namespace std;
-
- // 神经元结构
- double nv[1002], nu[1002], na[1002], nb[1002], nc[1002], nd[1002];
- int ntimes[1002];
-
- long long int pr[1002];
-
- struct synapse {
- int inID, D;
- double w;
- };
-
- vector<synapse> n2n[1002];
- vector<synapse> p2n[1002];
-
- static unsigned long Next = 1;
- /* RAND_MAX assumed to be 32767 */
- int myrand(void) {
- Next = Next * 1103515245 + 12345;
- return((unsigned)(Next/65536) % 32768);
- }
-
-
- int main() {
- int N, S, P, T;
- double deltaT;
- cin>>N>>S>>P>>T;
- cin>>deltaT;
-
- for (int id = 0; id < N;) {
- int RN;
- double v, u, a, b, c, d;
- cin>>RN>>v>>u>>a>>b>>c>>d;
- for (int j = 0; j < RN; ++j, ++id) {
- ntimes[id] = 0;
- nv[id] = v;
- nu[id] = u;
- na[id] = a;
- nb[id] = b;
- nc[id] = c;
- nd[id] = d;
- }
- }
- for (int i = 0; i < P; ++i) {
- long long int r;
- cin>>r;
- pr[i] = r;
- }
- synapse stmp;
- for (int i = 0; i < S; ++i) {
- int outID;
- cin>>outID>>stmp.inID>>stmp.w>>stmp.D;
- if (outID < N) {
- n2n[outID].emplace_back(stmp);
- }
- else {
- p2n[outID - N].emplace_back(stmp); // 要记得 - N
- }
- }
-
- // 记录每个时刻的 IK !!!关键点 !!!
- double IK[1002][1003] = {0}; // 循环数组, IK[n][m], m的大小是要略大于 D的
- int NUM = 1003;
- //
- for (int t = 1; t <= T; ++t) { // 每个时刻
- //
- for (int i = 0; i < P; ++i) { // 每个脉冲源
- if (myrand() < pr[i]) { // 当 r > myrand() 时发放脉冲信号
- for (int j = 0; j < p2n[i].size(); ++j) {
- synapse ss = p2n[i][j];
- IK[ss.inID][(t + ss.D) % NUM] += ss.w; // 通过 % 来循环
- }
- }
- }
-
- // 更新每个时刻的神经元
- for (int i = 0; i < N; ++i) { // 每个神经元
- double ik = IK[i][t % NUM];
- double prev = nv[i], preu = nu[i];
- double v = prev + deltaT * (0.04 * prev * prev + 5 * prev + 140 - preu) + ik,
- u = preu + deltaT * na[i] * (nb[i] * prev - preu);
-
- if (v >= 30) { // 神经元发放脉冲
- for (int j = 0; j < n2n[i].size(); ++j) {
- synapse ss = n2n[i][j];
- IK[ss.inID][(t + ss.D) % NUM] += ss.w;
- }
- v = nc[i];
- u = nd[i] + u;
- ++ntimes[i];
- }
- nv[i] = v;
- nu[i] = u;
-
- IK[i][t % NUM] = 0; // 每个时刻下遍历某一神经元后要将当前的状态修改成0, 这样后续循环才不会出错。
- }
- }
-
- // 找出最后的答案
- double minVV = nv[0], maxVV = nv[0];
- int minTimes = ntimes[0], maxTimes = ntimes[0];
- for (int i = 1; i < N; ++i) {
- minVV = min(minVV, nv[i]);
- maxVV = max(maxVV, nv[i]);
- minTimes = min(minTimes, ntimes[i]);
- maxTimes = max(maxTimes, ntimes[i]);
- }
-
- cout<<fixed<<setprecision(3)<<minVV<<" "<<fixed<<setprecision(3)<<maxVV<<endl<<minTimes<<" "<<maxTimes<< endl;
-
- return 0;
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。