LA 6135 - Environment Protection simpson积分

求深度 d 使得从深度0到深度d 的middle layer的面积是 A。

一开始读错题意。 所以代码中的 A 是深度 ,ans 才是面积A。 变量名不一致。


#include <vector>
#include <list>
#include <map>
#include <set>
#include <deque>
#include <stack>
#include <cstring>
#include <bitset>
#include <algorithm>
#include <functional>
#include <numeric>
#include <utility>
#include <sstream>
#include <iostream>
#include <iomanip>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <ctime>
#include <assert.h>
#include <queue>
#define REP(i,n) for(int i=0;i<n;i++)
#define TR(i,x) for(typeof(x.begin()) i=x.begin();i!=x.end();i++)
#define ALLL(x) x.begin(),x.end()
#define SORT(x) sort(ALLL(x))
#define CLEAR(x) memset(x,0,sizeof(x))
#define FILLL(x,c) memset(x,c,sizeof(x))
using namespace std;
const double eps = 1e-9;
#define LL long long 
#define pb push_back
const int maxn  = 11000;

int W,D,k;
double A,ans;
double a[15],b[15],c[15],d[15];
int flag ;
double F(double x){  
      if(flag==1){
      	   double up = a[0];
      	   double tmp = x;
      	   for(int i=1;i<=k;i++){
      	        	up+= a[i]*tmp;
      	        	tmp *= x;
      	   }
      	   double down = b[0];
      	   tmp = x;
      	   for(int i=1;i<=k;i++){
      	   	    down += b[i]*tmp;
      	   	    tmp *= x;
      	   }
      	   //cout << up<< "  uppppp "<<down <<"  "<<x<<endl;
      	   double ans = up/down ;
      	   
      	   return  max(ans,-(A+0.0));
      } else if(flag ==2){
      	   double up = c[0];
      	   double tmp = x;
      	   for(int i=1;i<=k;i++){
      	        	up+= c[i]*tmp;
      	        	tmp *= x;
      	   }
      	   double down = d[0];
      	   tmp = x;
      	   for(int i=1;i<=k;i++){
      	   	    down += d[i]*tmp;
      	   	    tmp *= x;
      	   }
      	  // cout << up << "  "<<down<<endl;
      	   double ans = up/down ;
      	   return  max(ans,-(A+0.0));
      } 
      return 0;
}  
  
// 三点simpson法。这里要求F是一个全局函数    
double simpson(double a,double b){  
    double c =  a+(b-a)/2;  
    return (F(a) + 4*F(c) + F(b))*(b-a)/6;  
}  
// 自适应Simpson公式(递归过程)。已知整个区间[a,b]上的三点simpson值A   
double asr(double a , double b ,double eps ,double A){  
//	cout << a << " "<< b<< " "<<endl;
    double c = a+ (b-a)/2;  
    double L = simpson(a,c) ,R = simpson(c,b);  
   // cout << A << "  "<< L<< "  "<<R<<endl;
    if(fabs(A-L-R)<=15*eps) return L + R +(A-L-R)/15;  
    return asr(a,c,eps/2,L) + asr(c,b,eps/2,R);  
}  
// 自适应Simpson公式(主过程)    
double asr(double a, double b, double eps) {    
  return asr(a, b, eps, simpson(a, b));    
} 

double  get_ans(){
	flag =1;
	double ans = asr(0,W+0.0,1e-6);
	//cout << ans <<endl;
    flag =2 ;
    double ans2 = asr(0,W+0.0,1e-8);
    //cout << ans2 <<endl;
	ans -= ans2;
	return ans;
}
void solve(){
	 double left = 0;
	 double right = D+0.0;
	 int t = 100;
	 while(right-left>1e-9){
	     double  mid = (left + right)/2;
	     A = mid;
	     double t = get_ans();
	     if(t<ans){
	     	  left = mid;
	     }else{
	     	   right = mid;
	     }
	 }
	 printf("%.5lf\n",left);
	
}
int main(){
     while(~scanf("%d%d",&W,&D)){
     	scanf("%lf",&ans);
     	scanf("%d",&k);
     	for(int i=0;i<=k;i++)scanf("%lf",&a[i]);
     	for(int i=0;i<=k;i++)scanf("%lf",&b[i]);
     	for(int i=0;i<=k;i++)scanf("%lf",&c[i]);
     	for(int i=0;i<=k;i++)scanf("%lf",&d[i]);
     	solve();
     }
    return 0;
}

求F 的函数更改。。 积分不再是求两次

时间快了不少

#include <vector>  
#include <list>  
#include <map>  
#include <set>  
#include <deque>  
#include <stack>  
#include <cstring>  
#include <bitset>  
#include <algorithm>  
#include <functional>  
#include <numeric>  
#include <utility>  
#include <sstream>  
#include <iostream>  
#include <iomanip>  
#include <cstdio>  
#include <cmath>  
#include <cstdlib>  
#include <ctime>  
#include <assert.h>  
#include <queue>  
#define REP(i,n) for(int i=0;i<n;i++)  
#define TR(i,x) for(typeof(x.begin()) i=x.begin();i!=x.end();i++)  
#define ALLL(x) x.begin(),x.end()  
#define SORT(x) sort(ALLL(x))  
#define CLEAR(x) memset(x,0,sizeof(x))  
#define FILLL(x,c) memset(x,c,sizeof(x))  
using namespace std;  
const double eps = 1e-9;  
#define LL long long   
#define pb push_back  
const int maxn  = 11000;  
  
int W,D,k;  
double A,ans;  
double a[15],b[15],c[15],d[15];  
int flag ;  
double F(double x){    
      
           double up = a[0];  
           double tmp = x;  
           for(int i=1;i<=k;i++){  
                    up+= a[i]*tmp;  
                    tmp *= x;  
           }  
           double down = b[0];  
           tmp = x;  
           for(int i=1;i<=k;i++){  
                down += b[i]*tmp;  
                tmp *= x;  
           }  
           //cout << up<< "  uppppp "<<down <<"  "<<x<<endl;  
           double ans = up/down ;  
             
           ans = max(ans,-(A+0.0));  
       
           double up2 = c[0];  
           double tmp2 = x;  
           for(int i=1;i<=k;i++){  
                    up2+= c[i]*tmp2;  
                    tmp2 *= x;  
           }  
           double down2 = d[0];  
           tmp2 = x;  
           for(int i=1;i<=k;i++){  
                down2 += d[i]*tmp2;  
                tmp2 *= x;  
           }  
          // cout << up << "  "<<down<<endl;  
           double ans3 = up2/down2 ;  
           ans3 =  max(ans3,-(A+0.0));  
         
      return ans- ans3;  
}    
    
// 三点simpson法。这里要求F是一个全局函数      
double simpson(double a,double b){    
    double c =  a+(b-a)/2;    
    return (F(a) + 4*F(c) + F(b))*(b-a)/6;    
}    
// 自适应Simpson公式(递归过程)。已知整个区间[a,b]上的三点simpson值A     
double asr(double a , double b ,double eps ,double A){    
//  cout << a << " "<< b<< " "<<endl;  
    double c = a+ (b-a)/2;    
    double L = simpson(a,c) ,R = simpson(c,b);    
   // cout << A << "  "<< L<< "  "<<R<<endl;  
    if(fabs(A-L-R)<=15*eps) return L + R +(A-L-R)/15;    
    return asr(a,c,eps/2,L) + asr(c,b,eps/2,R);    
}    
// 自适应Simpson公式(主过程)      
double asr(double a, double b, double eps) {      
  return asr(a, b, eps, simpson(a, b));      
}   
  
double  get_ans(){  
     
    double ans = asr(0,W+0.0,1e-6);  
    //cout << ans <<endl;  
  
    return ans;  
}  
void solve(){  
     double left = 0;  
     double right = D+0.0;  
     int t = 100;  
     while(right-left>1e-9){  
         double  mid = (left + right)/2;  
         A = mid;  
         double t = get_ans();  
         if(t<ans){  
              left = mid;  
         }else{  
               right = mid;  
         }  
     }  
     printf("%.5lf\n",left);  
      
}  
int main(){  
     while(~scanf("%d%d",&W,&D)){  
        scanf("%lf",&ans);  
        scanf("%d",&k);  
        for(int i=0;i<=k;i++)scanf("%lf",&a[i]);  
        for(int i=0;i<=k;i++)scanf("%lf",&b[i]);  
        for(int i=0;i<=k;i++)scanf("%lf",&c[i]);  
        for(int i=0;i<=k;i++)scanf("%lf",&d[i]);  
        solve();  
     }  
    return 0;  
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值