求深度 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; }