ACM Steps_Chapter Four_Section1

Can you solve this equation?

#include <iostream>
#include <cstdio>
#include <cmath>
using namespace std;
double comp(double x)
{
	return ( 8*pow(x,4) + 7*pow(x,3) + 2*pow(x,2) + 3*x + 6 );
}
int main()
{
	int t;
 	double Y;
 	scanf("%d",&t);
 	while( t-- && scanf("%lf",&Y) )
 	{
  		if( comp(0.0) > Y || comp(100.0) < Y)
  	{
   	printf("No solution!\n");
   	continue;
  	}
  	double l = 0.0, r = 100.0 ;
  	while( r - l > 1e-6)
  	{
   		double mid = ( l + r ) / 2.0;
   		double ret = comp( mid );
   		if( ret < Y)
    		l = mid + 1e-6;
   		else
    		r = mid - 1e-6;
  	}
  	printf("%.4lf\n", (l + r) / 2.0);
 	}
 	return 0;
}

Strange fuction

/*
求函数的最小值,首先求导的导函数为:G(x) = 42 * x^6+48*x^5+21*x^2+10*x-y (0 <= x <=100)
分析导函数的,导函数为一个单调递增的函数。如果导函数的最大值小于0,
那么原函数在区间内单调递减。
即F(100)最小;如果但函数的最小值大于0,那么原函数在区间内单调递增,即F(0)最小。
如果导函数既有正又有负
又由于导函数是单增函数,所以必有先负后正,即原函数必有先减后增的性质。
求出导函数的零点就是原函数的最小值点。
求导函数最小值方法是2分法.
*/
#include<iostream>
#include <cstdio>
#include <cmath>
double Y;
double cpt( double x )      //导函数
{
	return ( 42 * pow(x,6) + 48 * pow(x,5) + 21*pow(x,2) + 10*x );
}
double ret( double x )     //求结果
{
	return ( 6 * pow(x,7)+8*pow(x,6)+7*pow(x,3)+5*x*x-Y*x );
}
int main()
{
	int t;
 	double s;
 	scanf ("%d",&t);
 	while( t-- && scanf("%lf",&Y) )
 	{
  		double l = 0.0, r = 100.0,mid;
  		while( r - l > 1e-8 )
  		{
   			mid = ( l + r ) / 2.0;
   			s = cpt( mid );
   			if ( s > Y )
    			r = mid - 1e-8;
   			else
    			l = mid + 1e-8;
  		}
  		mid = ( l + r ) / 2.0;
  		printf("%.4lf\n", ret(mid) );
 	}
 	return 0;
}

Pie

/*
题目大意是要办生日Party,有n个馅饼,有f个朋友,接下来是n个馅饼的半径。然后是分馅饼了,
注意咯自己也要,大家都要一样大,形状没什么要求,但都要是一整块的那种,
也就是说不能从两个饼中各割一小块来凑一块,像面积为10的和6的两块饼
(饼的厚度是1,所以面积和体积相等),
如果每人分到面积为5,则10分两块,6切成5,够分3个人,如果每人6,则只能分两个了!
题目要求我们分到的饼尽可能的大!

只要注意精度问题就可以了,一般WA 都是精度问题
运用2分搜索:
首先用总饼的体积除以总人数,得到每个人最大可以得到的V,
但是每个人手中不能有两片或多片拼成的一块饼,
最多只能有一片分割过得饼。用2分搜索时,把0设为left,把V 设为right。mid=(left+right)/2;
搜索条件是:以mid为标志,如果每块饼都可以分割出一个mid,那么返回true,
说明每个人可以得到的饼的体积可以
大于等于mid;如果不能分出这么多的mid,那么返回false,
说明每个人可以得到饼的体积小于等于mid。
(1)精度为:0.000001
(2)   pi 用反余弦求出,精度更高。
*/
#include <iostream>
 #include <stdio.h>
 #include <math.h>
 using namespace std;
 double pi = acos(-1.0);
 int F,N;
 double V[10001];
 bool test(double x)
 {
     int num=0;
     for(int i = 0; i < N;i++)
     {
         num += int(V[i]/x);
     }
     if(num>=F)
     return true;
     else return false;
 }
 int main()
 {
     int t,r;
     double v,max,left,right,mid;
     scanf("%d",&t);
     while(t--)
     {
         scanf("%d%d",&N,&F);
         F = F+1;
         for(int i = 0; i < N; i++)
         {
             scanf("%d",&r);
             V[i] = pi*r*r;
             v += V[i];
         }
         max = v/F;
         left = 0.0;
         right = max;
         while((right-left)>1e-6)//注意这里的精度问题。
         {
             mid = (left+right)/2;
             if(test(mid))
             left = mid;
             else right = mid;
         }
         printf("%.4f\n",mid);
     }
     return 0;
 }

Can you find it?

#include<iostream>
#include<algorithm>
using namespace std;
int L, N, M, s, x, flag, k;
int a[501], b[501], c[501], sum[250001];
int Judge(int p)
{
	int l, r, m;
	l=0;
   	r=k-1;
	if(sum[l]==p||sum[r]==p) 
	{   
		flag=1;
		return 1;
	}
	while(l<=r)
	{
   		m=(l+r)/2;
   		if(sum[m]==p)
		{   
			flag=1; 
			return 1; 
		}
   		else if(sum[m]>p) 
		   r=m-1;
   		else if(sum[m]<p) 
		   l=m+1;
	}
	return 0;
}
int main()
{
	int i, j, t=0;
	while(cin>>L>>N>>M)
	{
   		printf("Case %d:\n", ++t);
   		for(i=0;i<L;i++)
    		scanf("%d",&a[i]);
   		for(i=0;i<N;i++)
    		scanf("%d",&b[i]);
   		for(i=0, k=0;i<L;i++)
   		{
    		for(j=0;j<N;j++)
     			sum[k++]=a[i]+b[j];
   		}
		sort(sum,sum+k);
   		for(i=0;i<M;i++)
    		scanf("%d",&c[i]);
   		cin>>s;
   		while(s--)
   		{
    		cin>>x;
     		flag=0;
    		for(i=0;i<M;i++)
   			{ 
     			if(x-c[i]>sum[k-1]) 
				 	continue;
     			if(Judge(x-c[i]))   
				 	break;
			}
    		if(flag) 
				printf("YES\n");
    		else 
				printf("NO\n");
   		}
	}
	return 0;
}

Toxophily

/*
用公式,根据正交分解坐标系,得出方程的通式。
想 x^2*g/(2*v^2)*tan^2(?) - x*tan(?) +y + x^2*g/(2*v^2) = 0;
 即:a = g*pow(x,2)/(2*pow(v,2));
    b = -x;
    c = y + g*pow(x,2)/(2*pow(v,2));
根据求根公式求出根。
注意讨论:
(1) x==0&&y==0时,? = 0;
(2) x==0&&y>0时,?=90;
(3) 方程无解时 ?=-1;
(4) 方程的解为负数时,?=-1;(0<=?<=90)。
*/
#include <iostream>
#include <stdio.h>
#include <math.h>
using namespace std;
int main()
{
    int t;
    double a,b,c,angle,z;
    double x,y,v,g = 9.8,T,ans1,ans2;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%lf%lf%lf",&x,&y,&v);
        if(x==0&&y==0)
        printf("0\n");
        else if(x==0&&y>0)
        printf("90\n");
        else
        {
            a = g*pow(x,2)/(2*pow(v,2));
            b = -x;
            c = y+a;
            T = pow(b,2) - 4*a*c;
            angle = 0;
            if(T<0)
            printf("-1\n");
            else
            {
                ans1 = ((-b)+pow(T,1.0/2))/(2*a);
                ans2 = ((-b)-pow(T,1.0/2))/(2*a);
                if(ans1>=0) angle = atan(ans1);
                if(ans2>=0)
                {
                    z =  atan(ans2);
                    if(z<angle) angle = z;
                    printf("%.6f\n",angle);
                }
                if(ans1<0&&ans2<0)
                    printf("-1\n");
            }
        }
    }
    return 0;
}

Turn the corner

/*
思路:显然为了让车子能顺利通过弯道,我们应该使车子擦着左边那个墙角走,
在转弯的过程中,车子的右下端(点p)露在最外面,所以我们只需判断点p能否顺利通过就行。
下面就是数学知识了,我们可以建立p的横坐标关于θ的函数,这个画个图可以算出来,
现在给出其函数表达式:f(θ)=l*cos(θ)-(x*cos(θ)-d)/sin(θ).
f(θ)在区间(0,π/2)上先增后减,所以我们需要求出f(θ)的最大值,
若f(θ)<=y则车子可以通过,否则不能通过。

对于这样的一个先增后减的函数,我们可以用三分求出其极大值。
*/
#include<iostream>
#include<cstdio>
#include<cmath>

using namespace std;
const double PI=acos(-1.0);
const double eps=1.0e-6;
double x,y,l,d;

double f(double t)//计算右下方顶点的横坐标(离第一条竖直线的距离)
{
    return l*cos(t)-(x*cos(t)-d)/sin(t);
}

int main()
{
    double low,up,mid1,mid2;
    while(cin>>x>>y>>l>>d)
    {
        low=0;
        up=PI/2;
        while(up-low>=eps)
        {
            mid1=low+(up-low)/3;
            mid2=up-(up-low)/3;
            if(f(mid1)<=f(mid2))
                low=mid1;
            else
                up=mid2;
        }
        if(f(mid1)<=y)
            printf("yes\n");
        else
            printf("no\n");
    }
    return 0;
}

Cable master

#include<iostream>
#include<iomanip>
using namespace std;
double a[10005];
int N,K;
int check(double x)
{
    int i,sum=0;
    for(i=0;i<N;i++)
        sum+=(int)(a[i]/x);
    if(sum<K)  
		return 0;
    return 1;
}
int main()
{
    int i;
    double left,right,mid,max;
    while(scanf("%d%d",&N,&K)!=EOF)
    {
        if(N==0&&K==0) break;
        max=0;
        for(i=0;i<N;i++)
        {
            scanf("%lf",&a[i]);
            if(a[i]>max)
                max=a[i];
        }
        left=0;
		right=max;
        while(right-left>0.001)
        {
            mid=(right+left)/2;
            if(check(mid))  
				left=mid;
            else 
				right=mid;
        }
        printf("%.2lf\n",mid);
    }
    return 0;
}

Dome of Circus

/*
这个题虽然是三维的,但是可以很容易的转化到二维去
。来看X-Z这个平面,我们将所有的点进行圆周映射,然后将所有的点都投影到
X-Z平面的的第一象限去,然后问题就转化成了在X-Z平面上找到一条斜率为负
的直线L,L和X正方向、Z正方向围成的三角形包含所有点,如果假设L和X轴的
交点为R,和Z轴焦点为H,要求pi*H*R^2的值最小。
   L这条线必定和某一
个给定的点擦边,也就是经过那个点,我们假设它经过P(a, b), 并且L的斜率
为K(K < 0),那么L的方程就可以表示为 L:  y = K * (x - a) + b,则H和R就
可以利用这个方程表示出来:
*/
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <queue>
#define eps 1e-7
#include <set>
#include <vector>
using namespace std;
struct point{
    double x,y,z;
    point(){}
    point(double a, double b, double c){x = a, y = b, z = c;}
}p[11111];
int n,T;
double a,b,c;
double cal(double r){
    double h ,Max = 0;
    for(int i = 0; i < n; i ++){
        h = p[i].z * r / (r - sqrt(p[i].x * p[i].x + p[i].y * p[i].y));
        Max = max(h,Max);
    }
    return r * r * Max;
}
void thi(double &r, double &h){
    double low = 0.0, high = 10000;
    double m1,m2;
    while(low + eps < high){
        m1 = (low + high) / 2.0;
        m2 = (m1 + high) / 2.0;
        if(cal(m1) <= cal(m2)) high = m2;
        else {
            low = m1;
        }
    }
    r = low;
    h = -1;
    for(int i = 0; i < n; i ++){
        h = max(h,p[i].z * r / (r - sqrt(p[i].x * p[i].x + p[i].y * p[i].y)) );
    }
}
int main(){
    scanf("%d",&T);
    while(T --){
        scanf("%d",&n);
        for(int i = 0; i < n; i ++){
            scanf("%lf%lf%lf",&p[i].x,&p[i].y,&p[i].z);
        }
        double r,h;
        thi(r,h);
        printf("%.3f %.3f\n",h,r);
    }
	return 0;
}


原文地址:https://www.cnblogs.com/oldoldb/p/3311319.html