【解题报告】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
原文地址:https://www.cnblogs.com/syiml/p/3532292.html