zoukankan      html  css  js  c++  java
  • 辛普森积分

    这两天看了看辛普森积分,觉得这是很好的骗分工具,正好也比较简单,就随便写一写。这个东西对于三次以下的函数是正确的,但是对于三次以上的函数我们可以将其近似为低次函数套用Simpson公式,这个东西学名好像叫自适应Simpson积分。

    先附上公式

    算法的大概流程就是不断的递归求对应区间的积分,当当前层和下一层的相对误差比较小时就退出,从而得到比较准确的值,但是这个其实是可以被卡掉的,比如一段波动的区间,我们取到的值有可能都是上顶点,就会直接退出,然而这并不是最后的答案。所以一般这个算法都是用来骗分的,2333。

    附上代码

     1 double calc(double l,double r,double fl,double fr,double fm){
     2     return (r-l)/6.0*(fl+fr+4*fm);
     3 }
     4 double simpson(double l,double r,double mid,double fl,double fr,double fm,double s){
     5     double m1=(l+mid)/2.0,m2=(mid+r)/2.0;
     6     double f1=F(m1),f2=F(m2);
     7     double s1=calc(l,mid,fl,fm,f1),s2=calc(mid,r,fm,fr,f2);
     8     if(fabs(s-s1-s2)<eps)return s1+s2;
     9     return simpson(l,mid,m1,fl,fm,f1,s1)+simpson(mid,r,m2,fm,fr,f2,s2);
    10 }

    我一般在simpson函数里会将三个函数值一并传进去,否则在单次计算f的复杂度比较大时,会重复计算,浪费时间。

    hdu1724,纯板子题。

    这道题我写的还是不传函数值的版本,可以对照着看看

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <iostream>
     4 #include <algorithm>
     5 #include <cmath>
     6 #define eps 1e-10
     7 using namespace std;
     8 double a,b;
     9 int T;
    10 double f(double x){
    11     return b*sqrt(1-(x*x)/(a*a));
    12 }
    13 double calc(double l,double r){
    14     double mid=(l+r)/2.0;
    15     return (r-l)/6*(f(l)+f(r)+4*f(mid));
    16 }
    17 double simpson(double l,double r,double now){
    18     double mid=(l+r)/2.0;
    19     double n1=calc(l,mid),n2=calc(mid,r);
    20     if(fabs(now-n1-n2)<eps)return now;
    21     return simpson(l,mid,n1)+simpson(mid,r,n2);
    22 }
    23 int main(){
    24     scanf("%d",&T);
    25     double l,r,ans;
    26     while(T--){
    27         scanf("%lf%lf%lf%lf",&a,&b,&l,&r);
    28         ans=simpson(l,r,calc(l,r))*2;
    29         printf("%0.3f
    ",ans);
    30     }
    31 }
    View Code

    bzoj2178,求圆的面积并

    网上别人好像都是直接积,我是用了一个并查集,把连在一起的圆一起算,貌似这样被hack的概率比较小

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <iostream>
     4 #include <algorithm>
     5 #include <cmath>
     6 #define eps 1e-13
     7 #define N 1005
     8 using namespace std;
     9 int v[N][N],cnt[N];
    10 int n,fa[N],del[N],tot;
    11 int le[N],ri[N];
    12 int find(int x){return x==fa[x]?x:fa[x]=find(fa[x]);}
    13 struct data{
    14     double s,t;
    15     data(){}
    16     data(double a,double b){s=a,t=b;}
    17 }L[N];
    18 bool cmpdown(const data & a,const data & b){return a.s<b.s;}
    19 struct cir{
    20     double x,y,r;
    21     void read(){scanf("%lf%lf%lf",&x,&y,&r);}
    22 }p[N],d[N];
    23 double dis(cir a,cir b){return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));}
    24 bool cmpr(const cir & a,const cir & b){return a.r<b.r;}
    25 bool cmpl(const int & a,const int & b){return p[a].x-p[a].r<p[b].x-p[b].r;}
    26 bool check1(cir a,cir b){//包含
    27     if(dis(a,b)+a.r<=b.r)return 1;
    28     return 0;
    29 }
    30 bool check2(cir a,cir b){//相交
    31     if(dis(a,b)<=a.r+b.r)return 1;
    32     return 0;
    33 }
    34 double F(double x,int id){
    35     tot=0;
    36     for(int i=1;i<=cnt[id];i++){
    37         int now=v[id][i];
    38         if(x>p[now].x+p[now].r)continue;
    39         if(x<p[now].x-p[now].r)break;
    40         double l=sqrt(p[now].r*p[now].r-(p[now].x-x)*(p[now].x-x));
    41         L[++tot]=data(p[now].y-l,p[now].y+l);
    42     }
    43     sort(L+1,L+tot+1,cmpdown);
    44     double ans=0;
    45     for(int i=1,j=1;i<=tot;i++){
    46         j=i;double up=L[i].t;
    47         while(j<tot&&L[j+1].s<=up){j++;up=max(up,L[j].t);}
    48         ans+=up-L[i].s;i=j;
    49     }
    50     return ans;
    51 }
    52 double calc(double l,double r,double fl,double fr,double fm){
    53     return (r-l)/6.0*(fl+fr+4*fm);
    54 }
    55 double simpson(double l,double r,double fl,double fr,double fm,double s,int id){
    56     double mid=(l+r)/2.0,m1=(l+mid)/2.0,m2=(mid+r)/2.0;
    57     double f1=F(m1,id),f2=F(m2,id),s1=calc(l,mid,fl,fm,f1),s2=calc(mid,r,fm,fr,f2);
    58     if(fabs(s-s1-s2)<eps)return s1+s2;
    59     return simpson(l,mid,fl,fm,f1,s1,id)+simpson(mid,r,fm,fr,f2,s2,id);
    60 }
    61 int main(){
    62     memset(le,0x3f,sizeof le);
    63     memset(ri,-0x3f,sizeof ri);
    64     scanf("%d",&n);
    65     for(int i=1;i<=n;i++)p[i].read(),fa[i]=i;
    66     sort(p+1,p+n+1,cmpr);
    67     for(int i=1;i<=n;i++)
    68         for(int j=i+1;j<=n;j++)if(check1(p[i],p[j])){
    69             del[i]=1;
    70             break;
    71         }
    72     for(int i=1;i<=n;i++)if(!del[i])d[++tot]=p[i];
    73     n=tot;
    74     for(int i=1;i<=n;i++)p[i]=d[i];
    75     for(int i=1;i<=n;i++)
    76         for(int j=i+1;j<=n;j++)
    77             if(check2(p[i],p[j]))
    78                 fa[find(j)]=find(i);
    79     for(int i=1;i<=n;i++){
    80         int f=find(i);
    81         v[f][++cnt[f]]=i;
    82         le[f]=min(le[f],(int)(p[i].x-p[i].r));
    83         ri[f]=max(ri[f],(int)(p[i].x+p[i].r));
    84     }
    85     double ans=0;
    86     for(int i=1;i<=n;i++){
    87         if(cnt[i]){
    88             sort(v[i]+1,v[i]+cnt[i]+1,cmpl);
    89             double fl=F(le[i],i),fr=F(ri[i],i),fm=F((le[i]+ri[i])/2.0,i);
    90             ans+=simpson(le[i],ri[i],fl,fr,fm,calc(le[i],ri[i],fl,fr,fm),i);
    91         }
    92     }
    93     printf("%0.3lf
    ",ans);
    94     return 0;
    95 }
    View Code

    bzoj1502,转化完题面就是要求一些圆以及相邻圆公切线所包含的面积。

    我被一个地方坑了一上午,最后发现是因为我先把包含的圆去掉再算的切线。身败名裂

      1 #include <cstdio>
      2 #include <cstring>
      3 #include <iostream>
      4 #include <algorithm>
      5 #include <cmath>
      6 #define N 550
      7 #define eps 1e-5
      8 using namespace std;
      9 int tot,n,cnt;
     10 double alp;
     11 struct line{
     12     double x1,x2,y1,y2,K,B;
     13     bool operator < (const line & a)const{return x1<a.x1;}
     14 }l[N];
     15 struct cir{
     16     double x,r;
     17 }p[N],d[N];
     18 void solve(cir a,cir b){
     19     if(a.r==b.r){
     20         l[++cnt].x1=a.x;l[cnt].x2=b.x;
     21         l[cnt].y1=l[cnt].y2=a.r;
     22         l[cnt].K=0;
     23         l[cnt].B=a.r;
     24         return ;
     25     }
     26     if(a.r>b.r){
     27         double r1=a.r,r2=b.r,c=b.x-a.x;
     28         if(r2){
     29             double d=c*r2/(r1-r2);
     30             double e=sqrt(d*d-r2*r2);
     31             l[++cnt].x1=a.x+r1*r2/d;l[cnt].y1=r1*e/d;
     32             l[cnt].x2=b.x+r2*r2/d;l[cnt].y2=r2*e/d;
     33         }
     34         else{
     35             double d=sqrt(c*c-r1*r1);
     36             l[++cnt].x1=a.x+r1*r1/c;l[cnt].y1=r1*d/c;
     37             l[cnt].x2=b.x;l[cnt].y2=0;
     38         }
     39         l[cnt].K=(l[cnt].y2-l[cnt].y1)/(l[cnt].x2-l[cnt].x1);
     40         l[cnt].B=(l[cnt].y1)-l[cnt].K*l[cnt].x1;
     41         return ;
     42     }
     43     if(a.r<b.r){
     44         double r1=a.r,r2=b.r,c=b.x-a.x;
     45         double d=c*r1/(r2-r1);
     46         double e=sqrt(d*d-r1*r1);
     47         l[++cnt].x1=a.x-r1*r1/d;l[cnt].y1=r1*e/d;
     48         l[cnt].x2=b.x-r2*r1/d;l[cnt].y2=r2*e/d;
     49         l[cnt].K=(l[cnt].y2-l[cnt].y1)/(l[cnt].x2-l[cnt].x1);
     50         l[cnt].B=(l[cnt].y1)-l[cnt].K*l[cnt].x1;
     51         return ;
     52     }
     53 }
     54 double F(double x){
     55     double ans=0;
     56     for(int i=1;i<=cnt;i++){
     57         if(x>l[i].x2)continue;
     58         if(x<l[i].x1)break;
     59         ans=max(ans,l[i].K*x+l[i].B);
     60     }
     61     for(int i=1;i<=n;i++){
     62         if(x>p[i].x+p[i].r)continue;
     63         if(x<p[i].x-p[i].r)break;
     64         if(!p[i].r)continue;
     65         double now=(x-p[i].x);
     66         ans=max(ans,sqrt(p[i].r*p[i].r-now*now));
     67     }
     68     return ans*2.0;
     69 }
     70 double calc(double l,double r,double fl,double fr,double fm){
     71     return (r-l)/6.0*(fl+fr+4*fm);
     72 }
     73 double simpson(double l,double r,double mid,double fl,double fr,double fm,double s){
     74     double m1=(l+mid)/2.0,m2=(mid+r)/2.0;
     75     double f1=F(m1),f2=F(m2);
     76     double s1=calc(l,mid,fl,fm,f1),s2=calc(mid,r,fm,fr,f2);
     77     if(fabs(s-s1-s2)<eps)return s1+s2;
     78     return simpson(l,mid,m1,fl,fm,f1,s1)+simpson(mid,r,m2,fm,fr,f2,s2);
     79 }
     80 int del[N];
     81 double h[N],r[N],sum[N];
     82 int main(){
     83     scanf("%d%lf",&n,&alp);
     84     alp=tan(alp);
     85     for(int i=1;i<=n+1;i++)scanf("%lf",&h[i]),sum[i]=sum[i-1]+h[i];
     86     for(int i=1;i<=n;i++)scanf("%lf",&r[i]);
     87     for(int i=1;i<=n;i++)p[i].x=sum[i]/alp,p[i].r=r[i];
     88     p[n+1].x=sum[n+1]/alp;p[n+1].r=0;
     89     for(int i=1;i<=n;i++)if(fabs(p[i+1].x-p[i].x)>fabs(p[i+1].r-p[i].r))
     90         solve(p[i],p[i+1]);
     91     sort(l+1,l+cnt+1);
     92     for(int i=1;i<=n+1;i++)
     93         for(int j=1;j<=n+1;j++)if(i!=j&&!del[j])
     94             if(fabs(p[i].x-p[j].x)+p[i].r<=p[j].r){del[i]=1;break;}
     95     for(int i=1;i<=n+1;i++)if(!del[i])d[++tot]=p[i];
     96     n=tot;
     97     for(int i=1;i<=n;i++)p[i]=d[i];
     98     double l=p[1].x-p[1].r,r=p[n].x+p[n].r,mid=(l+r)/2.0;
     99     double fl=F(l),fr=F(r),fm=F(mid),s=calc(l,r,fl,fr,fm);
    100     double ans=simpson(l,r,mid,fl,fr,fm,s);
    101     printf("%0.2f
    ",ans);
    102     return 0;
    103 }
    View Code

    我就找到这三道水题,感觉这个也就是用来骗分,掌握了也没有什么坏处。

  • 相关阅读:
    MQTT服务器搭建--Mosquitto用户名密码配置
    linux下c语言获取当前时间
    Linux下用C获取当前时间
    iptraf:一个实用的TCP/UDP网络监控工具
    CentOS配制FTP服务器,并且能用root权限登录
    centos6.4搭建ftp服务器
    两台Linux主机互传文件可以使用SCP命令来实现
    Linux 技巧:让进程在后台可靠运行的几种方法
    Linux 下 c 语言 聊天软件
    RobotFrameWork(五)控制流之if语句——Run Keyword If
  • 原文地址:https://www.cnblogs.com/Ren-Ivan/p/8465102.html
Copyright © 2011-2022 走看看