ACM Steps_Chapter Seven_Section1

Shape of HDU

#include<stdio.h>
#include<stdlib.h>

struct xy
{
    int x;
    int y;
}d[1000];

int g(int a,int b,int c)
{
    int t;
    //公式:s=(x1-x3)*(y2-y3)-(x2-x3)*(y1-y3)
    //当s>0时,p1,p2,p3三个点呈逆时针
    //当s<0时,p1,p2,p3三个点呈顺时针
    t=(d[a].x-d[c].x)*(d[b].y-d[c].y)-(d[b].x-d[c].x)*(d[a].y-d[c].y);
    return t;
}

int main()
{
    int i,t,n;
    while(scanf("%d",&n),n)
    {
        for(i=0;i<n;i++)
        {
            scanf("%d %d",&d[i].x,&d[i].y);
        }
        for(i=0;i<n;i++)
        {
            //模n是因为当i=n-1的时候n+1,n+2会超出数据范围,所以从头开始为最后一个点和第一二个点判断直线的走向
            t=g(i%n,(i+1)%n,(i+2)%n);
            if(t<0)break;
        }
            if(t>=0)
                printf("convex\n");
            else
                printf("concave\n");
    }
    return 0;
}

You can Solve a Geometry Problem too

/*
算法简单说明:   
  首先判断以两条线段为对角线的矩形是否相交,如果不相交两条线段肯定也不相交。

(所谓以a1b2为对角钱的矩形就是以两边长为|a1.x – b2.x|和|a1.y – b2.y|
以及a1b2为对角线的矩形)。

如果相交的话,利用矢量叉乘判断两条线段是否相互跨越,如果相互跨越显然就相交,
反之则不相交。算法不难,但是一些特殊情况需要考虑到,比如两条相段共线且在断点处相交。 
    
  /********************************************************   * *   
    * 返回(P1-P0)*(P2-P0)的叉积。 *   
    * 若结果为正,则<P0,P1>在<P0,P2>的顺时针方向; *   
    * 若为0则<P0,P1><P0,P2>共线; *   
    * 若为负则<P0,P1>在<P0,P2>的在逆时针方向; *   
    * 可以根据这个函数确定两条线段在交点处的转向, *   
    * 比如确定p0p1和p1p2在p1处是左转还是右转,只要     *   
    *               求(p2-p0)*(p1-p0),若<0则左转,>0则右转,=0则   *   
    *               共线                                                                                     *   
    * *   
  \********************************************************/  
#include<stdio.h>
#include<stdlib.h>
typedef struct T
{
   double x,y;        
} point;
double judge( point p1,point p2, point p )//判断点是否在直线的两边 
{
     return ( p1.x-p.x )*( p2.y-p.y )-( p2.x-p.x )*( p1.y-p.y );       
}
bool on_segments( point p1, point p2, point p )//判断端点是不是在直线上 
{
      double max=p1.x>p2.x?p1.x:p2.x;//找出直线的左右端点的范围 
      double min=p1.x<p2.x?p1.x:p2.x;
      if( p.x>=min&&p.x<=max ) return true;
      else return false;     
}
bool segments( point p1,point p2,point q1,point q2 )
{
      double d1=judge( p1, p2, q1 );
      double d2=judge( p1, p2, q2 );
      double d3=judge( q1, q2, p1 );
      double d4=judge( q1, q2 ,p2 );
      if( d1*d2<0&&d3*d4<0 )   return true;
      if( d1==0 && on_segments( p1,p2,q1 ) )  return true;//d为0是平行的情况,这是我们就要考虑是不是端点在直线上 
      if( d2==0 && on_segments( p1,p2,q2 ) )  return true ; 
      if( d3==0 && on_segments( q1,q2,p1 ) )  return true;
      if( d4==0 && on_segments( q1,q2,p2 ) )  return true;
      return false;  
}
int main()
{
    point start[124],end[124];
    int n;
    while( scanf("%d",&n),n )
    {
        int sum=0;
        for( int i=1; i<=n; i++ )
        {
             scanf( "%lf%lf%lf%lf",&start[i].x,&start[i].y,&end[i].x,&end[i].y );     
        }
        for( int i=1; i<=n; i++ )
           for( int j=i+1; j<=n; j++ )
           {
               if( segments( start[i],end[i],start[j],end[j] ) )
                  sum++;  
           }
         printf( "%d\n",sum );     
    }
   return 0;    
}

Lifting the Stone

 #include<stdio.h>
 #include<math.h>
 #include<stdlib.h>
 #define MAXN 1000005
 struct centre
 {
        double x , y ;
 }point[MAXN];
 int cas , n ;
 struct centre get_centre()
 {
      struct centre ctr ;
      double area = 0 ; 
      ctr.x = ctr.y = 0 ;
      point[n] = point[0] ;
      for ( int i = 0 ; i < n ; ++ i )
      {
          area +=( ( point[i].x * point[i+1].y - point[i].y * point[i+1].x ) / 2.0 ) ; // 以原点为定点,求三角形面积 
          ctr.x += ( point[i].x * point[i+1].y - point[i].y * point[i+1].x ) * ( point[i].x + point[i+1].x ) ; 
          ctr.y += ( point[i].x * point[i+1].y - point[i].y * point[i+1].x ) * ( point[i].y + point[i+1].y ) ;
      }
      ctr.x /= ( area * 6 ) ; 
      ctr.y /= ( area * 6 ) ; 
      return ctr ;
 }
 int main ()
 {
     scanf ( "%d" , &cas ) ;
     while ( cas -- )
     {
           scanf ( "%d" , &n ) ;
           for ( int i = 0 ; i < n ; ++ i )
               scanf ( "%lf%lf" , &point[i].x , &point[i].y ) ;
           struct centre ctr = get_centre();
           printf ( "%.2lf %.2lf\n" , ctr.x , ctr.y ) ;
     }
     return 0 ;
 }

Surround the Trees

#include<stdio.h>
#include<math.h>
#include<cstdlib>
const int MAXN=109;
const double eps=1e-6;
struct point
{
    double x,y;
}p[MAXN],h[MAXN];//p数组用于存所有点,h数组用于存凸包点
double distance(point p1,point p2)
{
    return sqrt((p1.x-p2.x)*(p1.x-p2.x)+(p1.y-p2.y)*(p1.y-p2.y));  
}//   求两点之间的距离
double multiply(point sp,point ep,point op)
{
      return ((sp.x-op.x)*(ep.y-op.y)-(ep.x-op.x)*(sp.y-op.y));  
}//判断sp,ep,op是否满足左转,op是向量起始点,sp与op是两向量另外的端点
int cmp(const void *a,const void *b)
{//按极角排序
    point *p1=(point *)a;
    point *p2=(point *)b;
    double t=multiply(*p2,*p1,p[0]);
    if(t>eps)
		return 1;
    else if(fabs(t)<=eps)
    {
		if(distance(p[0],*p1)>distance(p[0],*p2))
			return 1;
		else
			return -1;
    }
    else
		return -1;
}
void anglesort(point p[],int n)
{//找到最左下方的点
    int i,k=0;
    point temp;
    for(i=1;i<n;i++)
        if(p[i].x<p[k].x||((p[i].x==p[k].x)&&(p[i].y<p[k].y)))
            k=i;
    temp=p[0],p[0]=p[k],p[k]=temp;
    qsort(p+1,n-1,sizeof(point),cmp);//找到左下点后再将左下点作为中心进行极角排序,从第p[1]个元素开始,共n-1个元素
}
void Graham_scan(point p[],point ch[],int n,int &len)
{//建立凸包
    int i,top=2;
    anglesort(p,n);
    if(n<3)
	{
        for(i=0,len=n;i<n;i++)
			ch[i]=p[i];
        return;//终止函数
    }
    ch[0]=p[0],ch[1]=p[1],ch[2]=p[2];
    p[n]=p[0];
    for(i=3;i<=n;i++)
	{
        while(multiply(ch[top],p[i],ch[top-1])<=0)
			top--;
        ch[++top]=p[i];
    }
    len=top+1;
}
int main()
{
    int i,n,len;
    while(scanf("%d",&n)!=EOF&&n)
	{
        for(i=0;i<n;i++)
			scanf("%lf %lf",&p[i].x,&p[i].y);
        Graham_scan(p,h,n,len);//p为所有的点h为凸包点len为凸包点的个数
        double sum=0;
        for(i=1;i<len;i++)
        {
           sum+=distance(h[i],h[i-1]);
        }
        printf("%.2lf\n",sum);
	}
    return 0;  
}

Pick-up sticks

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
typedef struct T
{
   double x,y;        
}point;    
point start[200024],end[200024];
inline double judge( point p1,point p2,point p )//判断点是否在直线的两边
{
    return ( ( p1.x-p.x )*( p2.y-p.y ) - ( p2.x-p.x )*( p1.y-p.y ) );       
}
inline bool on_megment( point p1,point p2,point p )//判断端点是不是在直线上
{
	double max=p1.x>p2.x?p1.x:p2.x;//找出直线的左右端点的范围 
	double min=p1.x<p2.x?p1.x:p2.x;
   	if( p.x>=min&&p.x<=max )   
	   	return true;
   	else
   		return false;       
}
bool megment( point p1,point p2,point q1,point q2 )
{
    double d1=judge( p1,p2,q1 );
    double d2=judge( p1,p2,q2 );
    double d3=judge( q1,q2,p1 );
    double d4=judge( q1,q2,p2 );
    if( d1*d2<0&&d3*d4<0 )
		return true;//如果都异侧就一定相交 
	if( d1==0&&on_megment( p1,p2,q1 ) )  
		return true;//d为0是平行的情况,这是我们就要考虑是不是端点在直线上 
	if( d2==0&&on_megment( p1,p2,q2 ) )  
		return true;
    if( d3==0&&on_megment( q1,q2,p1 ) ) 
		 return true;
    if( d4==0&&on_megment( q1,q2,p2 ) )
	 	 return true;
    return	false; 
}
int main()
{
    int n,hash[100024];

    while( scanf( "%d",&n ),n )
    {
       memset( hash, 0,sizeof( hash ) );
       int count=0;
       for( int i=1; i<=n; i++ )
        scanf( "%lf%lf%lf%lf",&start[i].x,&start[i].y,&end[i].x,&end[i].y );
        for( int i=1;i<=n; i++ )
           for( int j=i+1;j<=n; j++ )
           {
                if( megment( start[i],end[i],start[j],end[j] ) )
                {
                     hash[i]=1;//记录被覆盖的棍子 
                     count++;
                     break;
                }    
           }
           int sum=0;
           count=n-count;
           printf( "Top sticks:" );
           for( int i=1;i<=n; i++ )
           {
              if( 0==hash[i] )
              {
                 sum++;
                 printf( count==sum?" %d.\n":" %d,",i );     
              } 
           }      
    }
    return 0;    
}

Maple trees

/*
 凸包+最小圆覆盖
 枚举任意3点找其最小覆盖圆
(当为钝角三角形时不是外接圆,而是以其最长边为直径的圆)。
 当为外接圆时,半径公式为r=abc/4s;(推导为如下:
 由正弦定理,a/sinA=b/sinB=c/sinC=2R,得sinA=a/(2R),
 又三角形面积公式S=(bcsinA)/2,所以S=(abc)/(4R),故R=(abc)/(4S).
*/

#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <iostream>

using namespace std;

const int N = 105;
const double eps = 1e-8;

struct point {
    int x;
    int y;
}p[N], stack[N];

bool isZero(double x) {
    return (x > 0 ? x : -x) < eps;
}

double dis(point A, point B) {
    return sqrt((A.x-B.x)*(A.x-B.x)+(A.y-B.y)*(A.y-B.y));
}

double crossProd(point A, point B, point C) {
    return (B.x-A.x)*(C.y-A.y) - (B.y-A.y)*(C.x-A.x);
}

int cmp(const void *a, const void *b) {
    point *c = (point *)a;
    point *d = (point *)b;
    double k = crossProd(p[0], *c, *d);
    if (k<eps || (isZero(k)&&dis(p[0], *c)>dis(p[0], *d))) return 1;
    return -1;
}

int Graham(int n) {
    int x = p[0].x;
    int y = p[0].y;
    int mi = 0;
    for (int i=1; i<n; ++i) {
        if (p[i].x<x || (p[i].x==x&&p[i].y<y)) {
            x = p[i].x;
            y = p[i].y;
            mi = i;
        }
    }
    point tmp = p[mi];
    p[mi] = p[0];
    p[0] = tmp;
    qsort(p+1, n-1, sizeof(point), cmp);
    p[n] = p[0];
    for (int i=0; i<3; ++i) stack[i] = p[i];
    int top = 2;
    for (int i=3; i<n; ++i) {
        if (crossProd(stack[top-1], stack[top], p[i])<=eps && top>=2) --top;
        stack[++top] = p[i];
    }
    return top;
}

double max(double a, double b) {
    return a > b ? a : b;
}

int main() {
    int n;
    while (scanf("%d", &n), n) {
        for (int i=0; i<n; ++i) scanf ("%d%d", &p[i].x, &p[i].y);
        if (n == 1) printf ("0.50\n");
        else if (n == 2) printf ("%.2lf\n", dis(p[0], p[1])*0.50+0.50);
        else {
            int top = Graham(n);
            double maxr = -1;
            double a, b, c, r, s;
            for (int i=0; i<top; ++i) {//枚举凸包上的点 
                for (int j=i+1; j<top; ++j) {
                    for (int k=j+1; k<=top; ++k) {
                        a = dis(stack[i], stack[j]);
                        b = dis(stack[i], stack[k]);
                        c = dis(stack[j], stack[k]);
                        if (a*a+b*b<c*c || a*a+c*c<b*b || b*b+c*c<a*a) r = max(max(a, b), c) / 2.0;//钝角 
                        else {
                            s = fabs(crossProd(stack[i], stack[j], stack[k])) / 2.0;
                            r = a * b * c / (s * 4.0);//三角形外接圆公式 
                        }                
                        if (maxr < r) maxr = r;
                    }
                }
            }
            printf ("%.2lf\n", maxr+0.5);
        }
    }
    return 0;
}

最大三角形

/*
 *  题目要求:求三角形的最大面积 
 *  方法:凸包+枚举凸包上的点 
 */
 
 #include <cmath>
 #include <cstdio>
 #include <cstdlib>
 #include <iostream>
 
 using namespace std;
 
 const int N = 50005;
 const double eps = 1e-8;
 
 struct point {
     int x;
     int y;
 }p[N], stack[N];
 
 bool isZero(double x) {
     return (x > 0 ? x : -x) < eps; 
 }
 
 double dis(point A, point B) {
     return sqrt((A.x-B.x)*(A.x-B.x)+(A.y-B.y)*(A.y-B.y));
 }
 
 int crossProd(point A, point B, point C) {
     return (B.x-A.x)*(C.y-A.y) - (B.y-A.y)*(C.x-A.x);
 }
 
 int cmp(const void *a, const void *b) {
     point *c = (point *)a;
     point *d = (point *)b;
     double k = crossProd(p[0], *c, *d);
     if (k<eps || (isZero(k)&&dis(p[0], *c)>dis(p[0], *d))) return 1;
     return -1;
 }
 
 int Graham(int n) {
     int x = p[0].x;
     int y = p[0].y;
     int mi = 0;
     for (int i=1; i<n; ++i) {
         if (p[i].x<x || (p[i].x==x&&p[i].y<y)) {
             x = p[i].x;
             y = p[i].y;
             mi = i;
         }
     }
     point tmp = p[mi];
     p[mi] = p[0];
     p[0] = tmp;
     qsort(p+1, n-1, sizeof(point), cmp);
     p[n] = p[0];
     for (int i=0; i<3; ++i) stack[i] = p[i];
     int top = 2;
     for (int i=3; i<n; ++i) {
         while (crossProd(stack[top-1], stack[top], p[i])<=eps && top>=2) --top;
         stack[++top] = p[i];
     }
     return top;    
 }
 
 double maxTrangle(int n) {
     int top = Graham(n);
     double area, maxArea = 0;
     for (int i=0; i<top; ++i) {
         for (int j=i+1; j<top; ++j) {
             for (int k=j+1; k<=top; ++k) {
                 area = crossProd(stack[i], stack[j], stack[k]);
                 if (maxArea < area) maxArea = area; 
             }
         }
     }
     return maxArea * 0.5;
 }
 
 int main() {
     int n;
     while (scanf("%d", &n) != EOF) {
         for (int i=0; i<n; ++i) scanf ("%d%d", &p[i].x, &p[i].y);
         double ans = maxTrangle(n);
         printf ("%.2lf\n", ans);
     }
     return 0;
 }

Assignments

/*
思路:贪心,a中最小的与b中最大的组合,即一个升序,一个降序排列即可。
因为假设(a0,b0),(a1,b1)两组数,
a0>a1&&b0>b1则很明显max(a0+b0-t,0)+max(a1+b1-t,0)>=max(a0+b1-t,0)+max(a1+b0-t,0)。。
即(a1,b0),(a0,b1)比(a0,b0),(a1,b1)组合更好。
就上面的证明:假设a1+b1>=t; 则前面等于a0+b0+a1+b1-2t,后面也是。
            假设a1+b1<t,且其它都为正,前面等于a0+b0-t。
			后面a0+b0+a1+b1-2t==a0+b0-t+负数明显小于前者。
                        其它有为负数的就不用说了。。。
                        */
 #include <iostream>
 #include<algorithm>
 using namespace std;
 int cmp(int a,int b)
 {
       return a>b;
 }
 int main()
 {
       int i,n,t,sum;
       int a[1010],b[1010];
       while(cin>>n>>t)
       {
             sum=0;
            for(i=0;i<n;i++)
            cin>>a[i];
            for(i=0;i<n;i++)
            cin>>b[i];
            sort(a,a+n);
            sort(b,b+n,cmp);
            for(i=0;i<n;i++)
            {
                  if(a[i]+b[i]>t)
                  sum+=(a[i]+b[i]-t);
            }
            cout<<sum<<endl;
       }
 
 }



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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值