• 【解题报告】POJ-1467 Symbolic Derivation


    原题地址:http://poj.org/problem?id=1467

    题目大意:

    对一个式子求导,给的式子包括常量,字母x,+,-,*,/,ln()运算符,任意嵌套的括号。求的导数式子不用化简,如1*x这样的式子不用变成x。下面给出了一些求导规则和运算优先级:

    1.乘除的优先级大于加减。

    2.同优先级结合性从左往右。

    3. 求导规则: 

    (a + b)' = a' + b'
    (a - b)' = a' - b'
    (a * b)' = (a' * b + a * b')
    (a / b)' = (a' * b - a * b') / b^2 Note: 写 b^2 而不是 (b*b)
    ln(a)' = (a')/(a)
    x' = 1
    常数的导数 = 0

    要注意的是,如上所给的规则中,有括号的部分要在求导式子中相应的加上括号。如:

    输入1*1

    输出(0*1+1*0)

    这里的括号不能去掉。

    解题思路:

    将整个式子当做一个字符串来处理。

    如果这个字符串是一个数字,则求导结果是 0

    如果这个字符串是一个x,则求导结果是 1

    否则,找到最后计算的那一个运算符(这个字符不能在任何括号里),如:" (2*ln(x+1.7)-x*x)/((-7)+3.2*x*x)+(x+3*x)*x "中,先最后计算的运算符是红色的加号。然后以这个加号为分界点,将整个式子分解成两部分,“ (2*ln(x+1.7)-x*x)/((-7)+3.2*x*x) ” 和“(x+3*x)*x” 然后根据加法求导法则,分别求两部分的导数,则将两部分分别递归一遍。

    若没有找到上一条所述的运算符(即整个字符串包含在括号里,或者为ln运算)

    如果是整个括号包含的字符串,则去掉这个括号得到的字符串递归一遍。

    如果是ln()运算符,则根据ln()求导法则递归。

    解题代码:

      1 #include<stdio.h>
      2 #include<string.h>
      3 #include<iostream>
      4 #include<stack>
      5 using namespace std;
      6 class String
      7 {
      8 public:
      9     char s[105];
     10     String(){s[0]=0;}
     11     String(String& s1){strcpy(s,s1.s);}
     12     bool isnum();
     13 };
     14 char ans[105];
     15 ostream& operator<<(ostream& out,String &s1)
     16 {
     17     cout<<s1.s;
     18     return out;
     19 }
     20 bool String::isnum()
     21 {
     22     int i=0;
     23     if(s[0]=='-') i++;
     24     for(;s[i];i++)
     25     {
     26         if(s[i]=='.'||(s[i]>='0'&&s[i]<='9')) ;
     27         else break;
     28     }
     29     if(!s[i]) return true;
     30     else return false;
     31 }
     32 void qiudao(String s1);
     33 void jia(String s1,String s2)
     34 {
     35     qiudao(s1);
     36     strcat(ans,"+");
     37     qiudao(s2);
     38 }
     39 void jian(String s1,String s2)
     40 {
     41     qiudao(s1);
     42     strcat(ans,"-");
     43     qiudao(s2);
     44 }
     45 void cheng(String s1,String s2)
     46 {
     47     strcat(ans,"(");
     48     qiudao(s1);
     49     strcat(ans,"*");
     50     strcat(ans,s2.s);
     51     strcat(ans,"+");
     52     strcat(ans,s1.s);
     53     strcat(ans,"*");
     54     qiudao(s2);
     55     strcat(ans,")");
     56 }
     57 void chu(String s1,String s2)
     58 {
     59     strcat(ans,"(");
     60     qiudao(s1);
     61     strcat(ans,"*");
     62     strcat(ans,s2.s);
     63     strcat(ans,"-");
     64     strcat(ans,s1.s);
     65     strcat(ans,"*");
     66     qiudao(s2);
     67     strcat(ans,")/");
     68     strcat(ans,s2.s);
     69     strcat(ans,"^2");
     70 }
     71 void ln(String s1)
     72 {
     73     strcat(ans,"(");
     74     qiudao(s1);
     75     strcat(ans,")/(");
     76     strcat(ans,s1.s);
     77     strcat(ans,")");
     78 }
     79 void qiudao(String s1)
     80 {
     81     int i;
     82     if(s1.isnum()) {strcat(ans,"0");return ;}//如果字符串表示一个数字,则求导结果为 0
     83     if(strcmp(s1.s,"x")==0) {strcat(ans,"1");return ;}//如果字符串是一个x,则求导结果为 1
     84     int len=strlen(s1.s);
     85     //下面用于计算优先级最低的一个运算符。
     86     int n=-1,you=3;
     87     for(i=0;s1.s[i];i++)
     88     {
     89         if(i!=0&&((s1.s[i]=='+'||s1.s[i]=='-')&&you>=1)) {n=i;you=1;break;}
     90         if(i!=0&&((s1.s[i]=='*'||s1.s[i]=='/')&&you>=2)) {n=i;you=2;}
     91         if(s1.s[i]=='(')
     92         {
     93             int n=1;
     94             while(n)
     95             {
     96                 i++;
     97                 if(s1.s[i]=='(')n++;
     98                 if(s1.s[i]==')')n--;
     99             }
    100         }
    101     }
    102     if(you!=3)
    103     {
    104         String ss1,ss2;
    105         strncpy(ss1.s,s1.s,n);
    106         ss1.s[n]=0;
    107         strncpy(ss2.s,&s1.s[n+1],len-n-1);
    108         ss2.s[len-n-1]=0;
    109         switch(s1.s[n])
    110         {
    111             case '+':jia(ss1,ss2);break;
    112             case '-':jian(ss1,ss2);break;
    113             case '*':cheng(ss1,ss2);break;
    114             case '/':chu(ss1,ss2);break;
    115         }
    116         return ;
    117     }
    118     if(s1.s[0]=='('&&s1.s[len-1]==')')
    119     {
    120         String s2;
    121         strncpy(s2.s,s1.s+1,len-2);
    122         s2.s[len-2]=0;
    123         strcat(ans,"(");
    124         qiudao(s2);
    125         strcat(ans,")");
    126         return ;
    127     }
    128     if(strncmp(s1.s,"ln(",3)==0&&s1.s[len-1]==')')
    129     {
    130         String ss1;
    131         strncpy(ss1.s,s1.s+3,len-4);
    132         ss1.s[len-4]=0;
    133         ln(ss1);
    134     }
    135 }
    136 int main()
    137 {
    138     String s1;
    139     int i;
    140     while(cin>>s1.s)
    141     {
    142         ans[0]=0;
    143         qiudao(s1);
    144         for(i=0;ans[i];i++)
    145         {
    146             if(ans[i+1]=='-')
    147             {
    148                 if(ans[i]=='+') {cout<<'-';i++;continue;}
    149                 if(ans[i]=='-') {cout<<'+';i++;continue;}
    150             }
    151             cout<<ans[i];
    152         }
    153         cout<<endl;
    154     }
    155     return 0;
    156 }
    View Code
  • 相关阅读:
    C# 日期帮助类【原创】
    C# 发送邮件
    每日一题力扣453
    每日力扣628
    每日一题力扣41巨坑
    每日一题力扣274
    每日一题力扣442有坑
    每日一题力扣495
    每日一题力扣645
    每日一题力扣697
  • 原文地址:https://www.cnblogs.com/syiml/p/3532292.html
Copyright © 2020-2023  润新知