PTA L3-023计算图

题意

给一个表达式的计算图,和输入变量的值。求解表达式的值和对每个输入变量的偏导。
题目链接

如何计算值

从输入变量正向拓扑排序,就可以保证在计算某个节点的值前,它的父节点计算过。于是就可以通过运算符计算当前节点的值。

第一个优化

运算符有6种,用if-else 不美观,可写6个函数,然后存在函数指针数组里。
运算符有单目和双目,参数不一致,可用数组来存放参数

如何计算梯度

假设终点为f
偏导法则 fx = fu*ux+fv*vx+...
所以对于节点u,已知fu,可以更新它的父节点v的fv,fv+=fu*uv,当v的儿子都遍历过后。fv得到最终答案
所以可以使用从f逆向拓扑排序遍历。

第二个优化

更新父节点的偏导值时也可以使用函数指针数组
关键代码

struct Node{
    int cmd;
    double v, fv;
    Node* pa[2];
};
double (*f[10])(Node** pa)={NULL,add,minus, mut,exp_, ln_, sin_};
void (*Df[10])(Node** pa, double fv)={NULL, Dadd, Dminus, Dmut, Dexp_, Dln_, Dsin_};
int q[MAXN];
int topo() {
    int l=0, r=0;
    for(int i=0; i<n; i++) {
        if(!in[i]) q[r++]=i;
    }
    while(l<r) {
        int u=q[l++];
        if(nodes[u].cmd) {
            nodes[u].v = f[nodes[u].cmd](nodes[u].pa);
        }
        for(int i=0; i<G[u].size(); i++) {
            int v=G[u][i];
            --in[v];
            if(in[v]==0) q[r++]=v;
        }
    }
    return q[r-1];
}
void Dtopo(int s) {
    int l=0, r=0;
    q[r++]=s;
    while(l<r) {
        int u=q[l++];
        if(nodes[u].cmd) {
            Df[nodes[u].cmd](nodes[u].pa, nodes[u].fv);
        }
        for(int i=0; i<IG[u].size(); i++) {
            int v=IG[u][i];
            --out[v];
            if(!out[v]) q[r++] = v;
        }
    }
}

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  • importUIKit classViewController:UITabBarController{ enumD...
    明哥_Young阅读 9,481评论 1 10
  • ORA-00001: 违反唯一约束条件 (.) 错误说明:当在唯一索引所对应的列上键入重复值时,会触发此异常。 O...
    我想起个好名字阅读 11,005评论 0 9
  • 官网 中文版本 好的网站 Content-type: text/htmlBASH Section: User ...
    不排版阅读 10,025评论 0 5
  • 持续更新,也欢迎Nodejs大牛进QQ群讨论:541925216参考网址:https://github.com/d...
    superchen阅读 11,344评论 0 0
  • 神奇的蒜酶——大蒜酵素 蒜氨酸:大蒜切割或研磨被破坏时,蒜氨酸在酶的作用下,很快变为蒜素。蒜素在降低血脂和防止凝血...
    快乐_4a34阅读 5,915评论 0 0

友情链接更多精彩内容