当前位置:   article > 正文

CSP CCF: 202109-3 脉冲神经网络 (C++) 66分

202109-3

题目来源

计算机软件能力认证考试系统

解题思路

由于我有些看不懂这个题目,所以我是先找的他人的博客理解了一下题目。

这个博客写得很详细的(66分),有助于理解题目。 CSP 202109-3 脉冲神经网络(详解)_刘学.的博客-CSDN博客

所以我这里主要就是记录一下这道题啦,想到如何优化到100分,再更新。

代码

66分

  1. #include <iostream>
  2. #include <iomanip>
  3. using namespace std;
  4. // 神经元结构
  5. struct neuron {
  6. int ID, times;
  7. double prev, preu; //v, u; // 由于后续这个v、u用处不大,我就没写上了
  8. double a, b, c, d;
  9. };
  10. struct pluse {
  11. int ID;
  12. long long int r;
  13. };
  14. struct synapse {
  15. int outID, inID, D;
  16. double w;
  17. };
  18. neuron neurons[1001];
  19. pluse pluses[1001];
  20. synapse synapses[1001];
  21. void InputData(int N, int P, int S) {
  22. for (int id = 0; id < N;) {
  23. int RN;
  24. double v, u, a, b, c, d;
  25. cin>>RN>>v>>u>>a>>b>>c>>d;
  26. for (int j = 0; j < RN; ++j, ++id) {
  27. neurons[id].times = 0;
  28. neurons[id].prev = v;
  29. neurons[id].preu = u;
  30. neurons[id].ID = id;
  31. neurons[id].a = a;
  32. neurons[id].b = b;
  33. neurons[id].c = c;
  34. neurons[id].d = d;
  35. }
  36. }
  37. for (int i = 0; i < P; ++i) {
  38. long long int r;
  39. cin>>r;
  40. pluses[i].ID = N + i;
  41. pluses[i].r = r;
  42. }
  43. for (int i = 0; i < S; ++i) {
  44. cin>>synapses[i].outID>>synapses[i].inID>>synapses[i].w>>synapses[i].D;
  45. }
  46. }
  47. static unsigned long Next = 1;
  48. /* RAND_MAX assumed to be 32767 */
  49. int myrand(void) {
  50. Next = Next * 1103515245 + 12345;
  51. return((unsigned)(Next/65536) % 32768);
  52. }
  53. int main() {
  54. int N, S, P, T;
  55. double deltaT;
  56. cin>>N>>S>>P>>T;
  57. cin>>deltaT;
  58. InputData(N, P, S);
  59. // 记录每个时刻的 IK !!!关键点 !!!
  60. double IK[1001][2001] = {0}; // int IK[1001][100101];
  61. for (int t = 1; t <= T; ++t) { // 每个时刻
  62. for (int i = 0; i < P; ++i) { // 每个脉冲源
  63. if (myrand() < pluses[i].r) { // 当 r > myrand() 时发放脉冲信号
  64. for (int j = 0; j < S; ++j) { // 每个突触
  65. if (synapses[j].outID == i + N) {
  66. IK[synapses[j].inID][t + synapses[j].D] += synapses[j].w;
  67. }
  68. }
  69. }
  70. }
  71. }
  72. // 更新每个时刻的神经元
  73. for (int t = 1; t <= T; ++t) { // 每个时刻
  74. for (int i = 0; i < N; ++i) { // 每个神经元
  75. double ik = IK[i][t];
  76. double prev = neurons[i].prev, preu = neurons[i].preu;
  77. double v = prev + deltaT * (0.04 * prev * prev + 5 * prev + 140 - preu) + ik, // !!!0.04 not 0.004!!!
  78. u = preu + deltaT * neurons[i].a * (neurons[i].b * prev - preu);
  79. if (v >= 30) { // 神经元发放脉冲
  80. for (int j = 0; j < S; ++j) { // 对于每个突触
  81. if (synapses[j].outID == i) {
  82. IK[synapses[j].inID][t + synapses[j].D] += synapses[j].w; // += synapses[j].w; not synapses[synapses[j].inID].w;
  83. }
  84. }
  85. v = neurons[i].c;
  86. u = neurons[i].d + u;
  87. ++neurons[i].times;
  88. }
  89. neurons[i].prev = v;
  90. neurons[i].preu = u;
  91. }
  92. }
  93. // 找出最后的答案
  94. double minVV = neurons[0].prev, maxVV = neurons[0].prev;
  95. int minTimes = neurons[0].times, maxTimes = neurons[0].times;
  96. for (int i = 1; i < N; ++i) {
  97. minVV = min(minVV, neurons[i].prev);
  98. maxVV = max(maxVV, neurons[i].prev);
  99. minTimes = min(minTimes, neurons[i].times);
  100. maxTimes = max(maxTimes, neurons[i].times);
  101. }
  102. cout<<fixed<<setprecision(3)<<minVV<<" "<<fixed<<setprecision(3)<<maxVV<<endl<<minTimes<<" "<<maxTimes<< endl;
  103. return 0;
  104. }

-------------------------------------------- 更新 ----------------------------------------------

我的代码改得就差将大佬的代码复制粘贴了,可它还是超时超时66分。呜呜。 

贴上 100分 的大佬代码的链接  CSP认证202109T3-脉冲神经网络(优化)_nth2000的博客-CSDN博客  参考参考, 方便以后复习吧。

把 66 分的也给贴上,以后再看问题在哪里了吧:

  1. /* 66 */
  2. #include <iostream>
  3. #include <iomanip>
  4. #include <map>
  5. #include <vector>
  6. #include <fstream>
  7. using namespace std;
  8. // 神经元结构
  9. double nv[1002], nu[1002], na[1002], nb[1002], nc[1002], nd[1002];
  10. int ntimes[1002];
  11. long long int pr[1002];
  12. struct synapse {
  13. int inID, D;
  14. double w;
  15. };
  16. vector<synapse> n2n[1002];
  17. vector<synapse> p2n[1002];
  18. static unsigned long Next = 1;
  19. /* RAND_MAX assumed to be 32767 */
  20. int myrand(void) {
  21. Next = Next * 1103515245 + 12345;
  22. return((unsigned)(Next/65536) % 32768);
  23. }
  24. int main() {
  25. int N, S, P, T;
  26. double deltaT;
  27. cin>>N>>S>>P>>T;
  28. cin>>deltaT;
  29. for (int id = 0; id < N;) {
  30. int RN;
  31. double v, u, a, b, c, d;
  32. cin>>RN>>v>>u>>a>>b>>c>>d;
  33. for (int j = 0; j < RN; ++j, ++id) {
  34. ntimes[id] = 0;
  35. nv[id] = v;
  36. nu[id] = u;
  37. na[id] = a;
  38. nb[id] = b;
  39. nc[id] = c;
  40. nd[id] = d;
  41. }
  42. }
  43. for (int i = 0; i < P; ++i) {
  44. long long int r;
  45. cin>>r;
  46. pr[i] = r;
  47. }
  48. synapse stmp;
  49. for (int i = 0; i < S; ++i) {
  50. int outID;
  51. cin>>outID>>stmp.inID>>stmp.w>>stmp.D;
  52. if (outID < N) {
  53. n2n[outID].emplace_back(stmp);
  54. }
  55. else {
  56. p2n[outID - N].emplace_back(stmp); // 要记得 - N
  57. }
  58. }
  59. // 记录每个时刻的 IK !!!关键点 !!!
  60. double IK[1002][1003] = {0}; // 循环数组, IK[n][m], m的大小是要略大于 D的
  61. int NUM = 1003;
  62. //
  63. for (int t = 1; t <= T; ++t) { // 每个时刻
  64. //
  65. for (int i = 0; i < P; ++i) { // 每个脉冲源
  66. if (myrand() < pr[i]) { // 当 r > myrand() 时发放脉冲信号
  67. for (int j = 0; j < p2n[i].size(); ++j) {
  68. synapse ss = p2n[i][j];
  69. IK[ss.inID][(t + ss.D) % NUM] += ss.w; // 通过 % 来循环
  70. }
  71. }
  72. }
  73. // 更新每个时刻的神经元
  74. for (int i = 0; i < N; ++i) { // 每个神经元
  75. double ik = IK[i][t % NUM];
  76. double prev = nv[i], preu = nu[i];
  77. double v = prev + deltaT * (0.04 * prev * prev + 5 * prev + 140 - preu) + ik,
  78. u = preu + deltaT * na[i] * (nb[i] * prev - preu);
  79. if (v >= 30) { // 神经元发放脉冲
  80. for (int j = 0; j < n2n[i].size(); ++j) {
  81. synapse ss = n2n[i][j];
  82. IK[ss.inID][(t + ss.D) % NUM] += ss.w;
  83. }
  84. v = nc[i];
  85. u = nd[i] + u;
  86. ++ntimes[i];
  87. }
  88. nv[i] = v;
  89. nu[i] = u;
  90. IK[i][t % NUM] = 0; // 每个时刻下遍历某一神经元后要将当前的状态修改成0, 这样后续循环才不会出错。
  91. }
  92. }
  93. // 找出最后的答案
  94. double minVV = nv[0], maxVV = nv[0];
  95. int minTimes = ntimes[0], maxTimes = ntimes[0];
  96. for (int i = 1; i < N; ++i) {
  97. minVV = min(minVV, nv[i]);
  98. maxVV = max(maxVV, nv[i]);
  99. minTimes = min(minTimes, ntimes[i]);
  100. maxTimes = max(maxTimes, ntimes[i]);
  101. }
  102. cout<<fixed<<setprecision(3)<<minVV<<" "<<fixed<<setprecision(3)<<maxVV<<endl<<minTimes<<" "<<maxTimes<< endl;
  103. return 0;
  104. }

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/2023面试高手/article/detail/647542
推荐阅读
相关标签
  

闽ICP备14008679号