zoukankan      html  css  js  c++  java
  • 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;
    }
    


  • 相关阅读:
    变量的创建和初始化
    HDU 1114 Piggy-Bank (dp)
    HDU 1421 搬寝室 (dp)
    HDU 2059 龟兔赛跑 (dp)
    HDU 2571 命运 (dp)
    HDU 1574 RP问题 (dp)
    HDU 2577 How to Type (字符串处理)
    HDU 1422 重温世界杯 (dp)
    HDU 2191 珍惜现在,感恩生活 (dp)
    HH实习 acm算法部 1689
  • 原文地址:https://www.cnblogs.com/oldoldb/p/3311319.html
Copyright © 2011-2022 走看看