NOIP2003TG 神经网络 topo

神经网络 (network)

【问题背景】

人工神经网络( Artificial Neural Network )是一种新兴的具有自我学习能力的计算系统,在模式识别、函数逼近及贷款风险评估等诸多领域有广泛的应用。对神经网络的研究一直是当今的热门方向,兰兰同学在自学了一本神经网络的入门书籍后,提出了一个简化模型,他希望你能帮助他用程序检验这个神经网络模型的实用性。

【问题描述】

在兰兰的模型中,神经网络就是一张有向图,图中的节点称为神经元,而且两个神经元之间至多有一条边相连,

下图是一个神经元的例子:

神经元〔编号为 1 )

图中, X1—X3 是信息输入渠道, Y1 - Y2 是信息输出渠道, C1 表示神经元目前的状态,

Ui 是阈值,可视为神经元的一个内在参数。

神经元按一定的顺序排列,构成整个神经网络。在兰兰的模型之中,神经网络中的神

经无分为几层;称为输入层、输出层,和若干个中间层。每层神经元只向下一层的神经元输出信息,只从上一层神经元接受信息。下图是一个简单的三层神经网络的例子 。

 兰兰规定, C i 服从公式:(其中 n 是网络中所有神经元的数目)

 

公式中的 Wji (可能为负值)表示连接 j 号神经元和 i 号神经元的边的权值。当 Ci 大于 0 时,该神经元处于兴奋状态,否则就处于平静状态。当神经元处于兴奋状态时,下一秒

它会向其他神经元传送信号,信号的强度为 Ci 。

如此.在输入层神经元被激发之后,整个网络系统就在信息传输的推动下进行运作。

现在,给定一个神经网络,及当前输入层神经元的状态( Ci ),要求你的程序运算出最后网

络输出层的状态。

【输入格式】

输入文件第一行是两个整数 n ( 1≤n≤100 )和 p 。接下来 n 行,每行两个整数,第 i + 1 行是神经元 i 最初状态和其阈值( Ui ),非输入层的神经元开始时状态必然为 0 。再下面 P 行,每行由两个整数 i , j 及一个整数 Wij ,表示连接神经元 i 、 j 的边权值为 Wij 。

【输出格式】

输出文件包含若干行,每行有两个整数,分别对应一个神经元的编号,及其最后的状态,两个整数间以空格分隔。 仅输出最后状态大于0的输出层神经元状态,并且按照编号由小到大顺序输出!

若输出层的神经元最后状态均不大于0 ,则输出 NULL 。

【输入样例】

5 6

1 0

1 0

0 1

0 1

0 1

1 3 1

1 4 1

1 5 1

2 3 1

2 4 1

2 5 1

【输出样例】

3 1

4 1

5 1

思路

 

坑爹的topo ,注意如何判断输出层以及如何更新每个点的状态

topo数组用来判断是否被删掉过,false表示已经被删掉,不存在

首先要知道如果当前节点没被激活就是c[i]<=0时,他的接收点j 的c[j] 的求和中不会包括 i

但是怎么处理减去阀值呢?

oo[i]=true表示更新I时,为第一次更新i ,这时要减去阀值 //相关:che

check表示当前删的点是不是输出层

 

代码

 

 1 //note on the text by booble 2017.03.01 at dh
 2 program network;
 3 const
 4   inf='network.in';
 5   outf='network.out';
 6 var
 7   i,j,n,p,s,t,tmp,ok:longint;
 8   check:boolean;  
 9   ru:array[1..100] of int64;         //入度
10   u,c:array[1..100] of int64;       //阀值和状态
11   w:array[1..100,1..100] of int64;   //quanzhi!
12   pd:array[1..100,1..100] of boolean;   //pd[i,j]=true表示i到j有边
13   topo,oo:array[1..100] of boolean; //oo[i]=true表示是第一次更新i 否则表示以前更新过
14                                     //topo数组用来判断是否被删掉过,false表示已经被删掉
15 procedure outgo;
16 begin
17   close(input);
18   close(output);
19   halt;
20 end;
21 
22 procedure dotopo(i:longint);
23 var
24   check,che2:boolean;
25 begin 
26    inc(ok);  topo[i]:=false;                   //标记已经删除过
27    che2:=true;    check:=false;
28    if c[i]<=0 then che2:=false;                //che2=true时表示当前点是活跃的
29    for j:= 1 to n do                           //枚举i指向哪个j
30    if pd[i,j] then
31     begin
32      dec(ru[j]);                               //删边
33      if che2 then c[j]:=c[j]+w[i,j]*c[i];      //如果i是活跃的更新j的c
34      if oo[j] then begin                       //如果是第一次就减去阀值并且做标记
35                     c[j]:=c[j]-u[j];  
36                     oo[j]:=false; 
37                    end; 
38      check:=true; 
39     end;
40   if check then c[i]:=0;                       //只有更新过j的i才不在最后一层
41 end;
42 
43 begin
44 
45   assign(input,inf);
46   assign(output,outf);
47   reset(input);
48   rewrite(output);
49   readln(n,p);
50   fillchar(topo,sizeof(topo),true);
51   fillchar(oo,sizeof(oo),true);
52   for i:= 1 to n do
53     readln(c[i],u[i]);
54 
55   for i:= 1 to p do
56   begin
57     readln(s,t,tmp);
58     inc(ru[t]);
59     w[s,t]:=tmp;     pd[s,t]:=true;
60   end;
61 
62   repeat
63     for i:= 1 to n do
64      if (ru[i]=0) and (topo[i]) then dotopo(i);
65   until ok=n;
66 
67   for i:= 1 to n do
68     if c[i]>0 then begin
69                        writeln(i,' ',c[i]);
70                        check:=true;
71                      end;
72 
73   if check=false then writeln('NULL');
74 
75   outgo;
76 end.

 

posted @ 2017-02-28 18:09  bobble  阅读(257)  评论(0编辑  收藏  举报