• POJ 1265 Area - [敲代码]

    2009年03月24日

    详见上一篇日志,POJ2954(http://sweetglue.blogbus.com/logs/36939861.html)

     

    #include
    #include
    #include
    using namespace std;
    
    struct Point
    {
    	int x, y;
    };
    
    #define MAX 105
    //加为了循环不越界
    Point points[MAX+1];
    
    int gcd(int i, int j)
    {
    	int a = max(i, j), b = min(i, j);
    	i = a%b;
    	while(i != 0)
    	{
    		a = b;
    		b = i;
    		i = a%b;
    	}
    	return b;
    }
    
    //计算在某条边上的整数点的数目(不包括端点),端点坐标必须为整数
    int countPointsOnSegment(Point p1, Point p2)
    {
    	int a = abs(p2.y - p1.y), b = abs(p2.x - p1.x);
    	if(a == 0 && b == 0)
    		return 0;
    	else if(a == 0)
    		return b - 1;
    	else if(b == 0)
    		return a - 1;
    	else
    		return gcd(a, b) - 1;
    }
    
    //计算在多边形边上的整数点的数目(不包括端点),端点坐标必须为整数
    int countPointsOnPolygon(int DIM)
    {
    	int res = 0;
    	for(int i = 0; i < DIM; i++)
    	{
    		res += countPointsOnSegment(points[i], points[i+1]);
    	}
    	return res;
    }
    
    int areaPoly2(int DIM)
    {
    	int res = 0;
    	for(int i = 0; i < DIM; i++)
    	{
    		res += (points[i].x + points[i+1].x)*(points[i+1].y - points[i].y);
    	}
    	return abs(res);
    }
    
    int countPointsInPolygon(int DIM)
    {
    	return (areaPoly2(DIM) - DIM - countPointsOnPolygon(DIM))/2 + 1;
    }
    
    int main()
    {
    	int t, cc, n;
    	scanf("%d", &t);
    	points[0].x = points[0].y = 0;
    	for(cc = 1; cc <= t; cc++)
    	{
    		scanf("%d", &n);
    		for(int i = 1; i <= n; i++)
    		{
    			scanf("%d%d", &points[i].x, &points[i].y);
    			points[i].x += points[i-1].x;
    			points[i].y += points[i-1].y;
    		}
    		points[n] = points[0];
    		int in = countPointsInPolygon(n);
    		int on = countPointsOnPolygon(n) + n;
    		double area = (double)areaPoly2(n) / 2.0;
    		printf("Scenario #%d:\n%d %d %.1lf\n\n", cc, in, on, area);
    	}
    	return 0;
    }
    
  • POJ 2954 Triangle - [敲代码]

    2009年03月24日

    Pick公式:a = e / 2 + i - 1 。其中a为多边形(顶点都在格点上)面积,e为多边形边上的格点数,i为多边形内部的格点数。

    则多边形内部整数坐标点数为:(2a-e)/2+1

     

    #include
    #include
    #include
    using namespace std;
    
    struct Point
    {
    	int x, y;
    };
    
    //多边形边数
    #define DIM 3
    //加1为了循环不越界
    Point points[DIM+1];
    
    int gcd(int i, int j)
    {
    	int a = max(i, j), b = min(i, j);
    	i = a%b;
    	while(i != 0)
    	{
    		a = b;
    		b = i;
    		i = a%b;
    	}
    	return b;
    }
    
    //计算在某条边上的整数点的数目(不包括端点),端点坐标必须为整数
    int countPointsOnSegment(Point p1, Point p2)
    {
    	int a = abs(p2.y - p1.y), b = abs(p2.x - p1.x);
    	if(a == 0 && b == 0)
    		return 0;
    	else if(a == 0)
    		return b - 1;
    	else if(b == 0)
    		return a - 1;
    	else
    		return gcd(a, b) - 1;
    }
    
    //计算在多边形边上的整数点的数目(不包括端点),端点坐标必须为整数
    int countPointsOnPolygon()
    {
    	int res = 0;
    	for(int i = 0; i < DIM; i++)
    	{
    		res += countPointsOnSegment(points[i], points[i+1]);
    	}
    	return res;
    }
    
    int areaPoly2()
    {
    	int res = 0;
    	for(int i = 0; i < DIM; i++)
    	{
    		res += (points[i].x + points[i+1].x)*(points[i+1].y - points[i].y);
    	}
    	return abs(res);
    }
    
    int countPointsInPolygon()
    {
    	return (areaPoly2() - DIM - countPointsOnPolygon())/2 + 1;
    }
    
    int main()
    {
    	while(true)
    	{
    		scanf("%d%d%d%d%d%d", &points[0].x, &points[0].y, &points[1].x, &points[1].y, &points[2].x, &points[2].y);
    		if(points[0].x == 0 && points[0].y == 0 && points[1].x == 0 && points[1].y == 0 && points[2].x == 0 && points[2].y == 0)
    			break;
    		points[3] = points[0];
    		printf("%d\n", countPointsInPolygon());
    	}
    	return 0;
    }
    

  • POJ 1118 Lining Up - [敲代码]

    2009年03月17日

    Tag:POJ

    每次选定一个点p,然后计算其他点与p构成的线段的斜率,记录斜率相同的最多的数目。

    很奇怪的是,同样是n2logn的算法,用vector后sort不超时,但用map超时

     

    #include
    #include
    #include
    #include
    using namespace std;
    
    struct Point
    {
    	double x,y;
    };
    
    Point points[705];
    
    double eps = 1e-6;
    
    bool same(double x, double y)
    {
    	return abs(x-y) < eps;
    }
    
    int main()
    {
    	int n;
    	double topp = 1e20;
    	while(scanf("%d", &n), n != 0)
    	{
    		int maxs = 1;
    		for(int i = 0; i < n; i++)
    		{
    			scanf("%lf%lf", &points[i].x, &points[i].y);
    		}
    		for(int i = 0; i < n; i++)
    		{
    			vector vect;
    			for(int j = 0; j < n; j++)
    			{
    				if(j == i)
    					continue;
    				if(same(points[i].x, points[j].x))
    					vect.push_back(topp);
    				else
    				{
    					vect.push_back((points[j].y-points[i].y)/(points[j].x-points[i].x));
    				}
    			}
    			sort(vect.begin(), vect.end());
    			int counts = 1;
    			for(int j = 1; j < vect.size(); j++)
    			{
    				if(same(vect[j], vect[j-1]))
    				{
    					counts++;
    				}
    				else
    				{
    					if(maxs < counts)
    						maxs = counts;
    					counts = 1;
    				}
    			}
    			if(maxs < counts)
    				maxs = counts;
    		}
    		printf("%d\n", maxs+1);
    	}
    	return 0;
    }
    

  • POJ 2653 Pick-up sticks - [敲代码]

    2009年03月17日

    这个题一个月前就在做,一直WA,百思不得其解,今天终于发现原来输出漏掉了逗号,郁闷。

    判断一个线段是否在另一个上面的问题,需要完全相交(不包括一个的端点在另一个上面)

     

    #include
    #include
    #include
    using namespace std;
    
    #define PI acos(-1)
    #define eps 1e-6
    
    typedef struct
    {
    	double x, y;
    } Point;
    
    typedef struct
    {
    	double x, y, r;
    } Circle;
    
    typedef struct
    {
    	double a, b, c;
    } Line;
    
    
    bool same(Point& p1, Point& p2)
    {
    	return abs(p1.x-p2.x) < eps && abs(p1.y-p2.y) < eps;
    }
    bool same(double x, double y)
    {
    	return abs(x-y) < eps;
    }
    
    double crossMul(Point p0, Point p1, Point p2)
    {
    	return (p2.x - p0.x) * (p1.y - p0.y) - (p1.x - p0.x) * (p2.y - p0.y);
    }
    
    //判断两线段是否相交(不包括一个端点在另一个上面)
    bool isIntesect(Point s1, Point e1, Point s2, Point e2)
    {
    	return max(s1.x, e1.x) >= min(s2.x, e2.x) && max(s2.x, e2.x) >= min(s1.x, e1.x) && max(s1.y, e1.y) >= min(s2.y, e2.y) && max(s2.y, e2.y) >= min(s1.y, e1.y) && crossMul(s1, e1, s2)*crossMul(s1,e2, e1) > 0 && crossMul(s2, e2, s1)*crossMul(s2,e1, e2) > 0;
    }
    
    Point lines[100005][4];
    bool ison[100005];
    
    int main()
    {
    	int n;
    	while(scanf("%d", &n), n != 0)
    	{
    		for(int i = 0; i < n; i++)
    		{
    			scanf("%lf%lf%lf%lf", &lines[i][0].x, &lines[i][0].y, &lines[i][1].x, &lines[i][1].y);
    			ison[i] = false;
    		}
    		bool init = false;
    		printf("Top sticks:");
    		for(int i = 0; i < n; i++)
    		{
    			for(int j = i + 1; j < n; j++)
    			{
    				if(isIntesect(lines[i][0], lines[i][1], lines[j][0], lines[j][1]))
    				{
    					ison[i] = true;
    					break;
    				}
    			}
    			if(!ison[i])
    			{
    				if(init)
    					printf(",");
    				init = true;
    				printf(" %d", i+1);
    			}
    		}
    		printf(".\n");
    	}
    	return 0;
    }
    
  • POJ1066Treasure Hunt - [敲代码]

    2009年03月17日

    密室是指定点p,依次判断p与金字塔四周所有点组成的线段与其他线段相交的次数,统计最小值。

    #include
    #include
    #include
    using namespace std;
    
    #define PI acos(-1)
    #define eps 1e-6
    
    typedef struct
    {
    	double x, y;
    } Point;
    
    typedef struct
    {
    	double x, y, r;
    } Circle;
    
    typedef struct
    {
    	double a, b, c;
    } Line;
    
    
    bool same(Point& p1, Point& p2)
    {
    	return abs(p1.x-p2.x) < eps && abs(p1.y-p2.y) < eps;
    }
    bool same(double x, double y)
    {
    	return abs(x-y) < eps;
    }
    
    double crossMul(Point p0, Point p1, Point p2)
    {
    	return (p2.x - p0.x) * (p1.y - p0.y) - (p1.x - p0.x) * (p2.y - p0.y);
    }
    
    //判断两线段是否相交(不包括一个端点在另一个上面)
    bool isIntesect(Point s1, Point e1, Point s2, Point e2)
    {
    	return max(s1.x, e1.x) >= min(s2.x, e2.x) && max(s2.x, e2.x) >= min(s1.x, e1.x) && max(s1.y, e1.y) >= min(s2.y, e2.y) && max(s2.y, e2.y) >= min(s1.y, e1.y) && crossMul(s1, e1, s2)*crossMul(s1,e2, e1) > 0 && crossMul(s2, e2, s1)*crossMul(s2,e1, e2) > 0;
    }
    
    int main()
    {
    	int n, min_count = INT_MAX, cur_count;
    	Point points[35][2], p, p0;
    	scanf("%d", &n);
    	for(int i = 0; i < n; i++)
    	{
    		scanf("%lf%lf%lf%lf", &points[i][0].x, &points[i][0].y, &points[i][1].x, &points[i][1].y);
    	}
    	points[n][0].x = 0; points[n][0].y = 0; points[n][1].x = 100; points[n][1].y = 0; n++;
    	points[n][0].x = 0; points[n][0].y = 0; points[n][1].x = 0; points[n][1].y = 100; n++;
    	points[n][0].x = 0; points[n][0].y = 100; points[n][1].x = 100; points[n][1].y = 100; n++;
    	points[n][0].x = 100; points[n][0].y = 0; points[n][1].x = 100; points[n][1].y = 100; n++;
    	scanf("%lf%lf", &p.x, &p.y);
    	for(int i = 0; i < n; i++)
    	{
    		for(int j = 0; j < 2; j++)
    		{
    			p0 = points[i][j];
    			cur_count = 0;
    			for(int k = 0; k < n; k++)
    			{
    				if(k != i)
    				{
    					if(isIntesect(p, p0, points[k][0], points[k][1]))
    						cur_count++;
    				}
    			}
    			if(cur_count < min_count)
    				min_count = cur_count;
    		}
    	}
    	printf("Number of doors = %d\n", min_count+1);
    	return 0;
    }