从零单排15

今天重新看刘汝佳的入门经典,果然有了不一样的感受

以前那本书看到第五章的重载运算符就很吃力了。。

现在经过一段时间的学习。。好多了。。

能感到动态规划那部分了。。。

然后就感觉吃力了。。

动态规划部分练习的还是太少,好多基本的模型还不知道。。。


刚刚趁学习遇到瓶颈做了三道计算几何,学习了

8. 计算几何
a) 判断点是否在线段上
b) 判断线段相交
c) 判断矩形是否包含点
d) 判断圆与矩形关系
e) 判断点是否在多边形内
f) 判断点到线段的最近点
g) 计算两个圆的公切线
h) 求矩形的并的面积
i) 求多边形面积
j) 求多边形重心
k) 求凸包


自己的代码没有对浮点数进行精度判断。。。

可见hdu的数据有多弱。。

题解:

hdu 1086:http://acm.hdu.edu.cn/showproblem.php?pid=1086

/*
计算几何-线段相交
套模版~
*/
#include<iostream>
using namespace std;
struct point 
{
	double x;
	double y;
};
point point1[105],point2[105];
struct line
{
	point start;
	point end;
};
double crossProduct(point p1,point p2,point p)//判断点是否在直线两边 
{
	return (p.x-p1.x)*(p2.y-p.y)-(p.y-p1.y)*(p2.x-p.x);
}
bool on_segment(point p1,point p2,point p)//判断点是否在线段上 
{
	double minx=min(p1.x,p2.x);
	double maxx=max(p1.x,p2.x);
	double miny=min(p1.y,p2.y);
	double maxy=max(p1.y,p1.y);
	if(minx<=p.x && maxx>=p.x && miny<=p.y && maxy>=p.y && crossProduct(p1,p2,p)==0)
	{
		return true;
	}
	else
	{
		return false;
	}
} 
bool segments_intersect(point p1,point p2,point p3,point p4)
{
	double d1=crossProduct(p1,p2,p3);
	double d2=crossProduct(p1,p2,p4);
	double d3=crossProduct(p3,p4,p1);
	double d4=crossProduct(p3,p4,p2);
	if(d1*d2<0 && d3*d4<0)
	{
		return true;
	}
	//d=0时为平行情况,此时需要考虑端点是否在线段上 
	else if(!d1 && on_segment(p3,p4,p1))
	{
		return true;
	}
	else if(!d2 && on_segment(p3,p4,p2))
	{
		return true;
	}
	else if(!d3 && on_segment(p1,p2,p3))
	{
		return true;
	}
	else if(!d4 && on_segment(p1,p2,p4))
	{
		return true;
	}
	else 
	{
		return false;
	}
}
int main()
{
	int n;
	while(cin>>n&&n!=0)
	{
		for(int i=1;i<=n;i++)
		{
			cin>>point1[i].x>>point1[i].y>>point2[i].x>>point2[i].y;
		}
		int cnt=0;
		for(int i=1;i<n;i++)
		{
			for(int j=i+1;j<=n;j++)
			{
				if(segments_intersect(point1[i],point2[i],point1[j],point2[j]))
				{
					cnt++;
				}
			}
		}
		cout<<cnt<<endl;
	}
	system("pause");
	return 0;
}
		

hdu 1147: http://acm.hdu.edu.cn/showproblem.php?pid=1147

/*
计算集合-线段相交
开一个flag[]数组标记该线段是否被覆盖 
依次遍历,若后续线段与之前线段相交,则将flag[之前线段]置0
最后统计flag为1的线段输出即可
*/
#include<iostream>
using namespace std;
struct point 
{
	double x;
	double y;
};
point point1[100005],point2[100005];
int ans[100005];
bool flag[100005];
double crossProduct(point p1,point p2,point p)//判断点是否在直线两边 
{
	return (p.x-p1.x)*(p2.y-p.y)-(p.y-p1.y)*(p2.x-p.x);
}
bool on_segment(point p1,point p2,point p)//判断点是否在线段上 
{
	double minx=min(p1.x,p2.x);
	double maxx=max(p1.x,p2.x);
	double miny=min(p1.y,p2.y);
	double maxy=max(p1.y,p1.y);
	if(minx<=p.x && maxx>=p.x && miny<=p.y && maxy>=p.y && crossProduct(p1,p2,p)==0)
	{
		return true;
	}
	else
	{
		return false;
	}
} 
bool segments_intersect(point p1,point p2,point p3,point p4)//判断线段相交 
{
	double d1=crossProduct(p1,p2,p3);
	double d2=crossProduct(p1,p2,p4);
	double d3=crossProduct(p3,p4,p1);
	double d4=crossProduct(p3,p4,p2);
	if(d1*d2<0 && d3*d4<0)
	{
		return true;
	}
	//d=0时为平行情况,此时需要考虑端点是否在线段上 
	else if(!d1 && on_segment(p3,p4,p1))
	{
		return true;
	}
	else if(!d2 && on_segment(p3,p4,p2))
	{
		return true;
	}
	else if(!d3 && on_segment(p1,p2,p3))
	{
		return true;
	}
	else if(!d4 && on_segment(p1,p2,p4))
	{
		return true;
	}
	else 
	{
		return false;
	}
}
int main()
{
	int n;
	while(cin>>n&&n!=0)
	{
		memset(flag,true,sizeof(flag));
		for(int i=1;i<=n;i++)
		{
			cin>>point1[i].x>>point1[i].y>>point2[i].x>>point2[i].y;
		}
		for(int i=1;i<n;i++)
		{
			for(int j=i+1;j<=n;j++)
			{
				if(segments_intersect(point1[i],point2[i],point1[j],point2[j]))
				{
					flag[i]=false;
					break;
				}
			}
		}
		int cnt=0;
		cout<<"Top sticks: ";
		for(int i=1;i<=n;i++)
		{
			if(flag[i])
			{
				ans[++cnt]=i;
			}
		}
		for(int i=1;i<cnt;i++)
		{
			cout<<ans[i]<<", ";
		}
		cout<<ans[cnt]<<"."<<endl;
	}
	system("pause");
	return 0;
}
			

hdu 1756: http://acm.hdu.edu.cn/showproblem.php?pid=1756

/*
计算几何-判断点是否在多边形内
垂直交叉点数判别法
从P向一“无穷远点”作射线,
如果P是多边形上边上,说明P在多边形内 
如果P在射线上,另作新射线,重新判断 
如果射线与多边形边相交,交点+1,最后判断总交点数奇偶性
*/
#include<iostream>
#include<cmath>
#define MAX 1000
using namespace std;
struct point 
{
	double x;
	double y;
};
point p[105],p1,p2;
double crossProduct(point p1,point p2,point p)//判断点是否在直线两边 
{
	return (p.x-p1.x)*(p2.y-p.y)-(p.y-p1.y)*(p2.x-p.x);
}
bool on_segment(point p1,point p2,point p)//判断点是否在线段上 
{
	double minx=min(p1.x,p2.x);
	double maxx=max(p1.x,p2.x);
	double miny=min(p1.y,p2.y);
	double maxy=max(p1.y,p1.y);
	if(minx<=p.x && maxx>=p.x && miny<=p.y && maxy>=p.y && crossProduct(p1,p2,p)==0)
	{
		return true;
	}
	else
	{
		return false;
	}
} 
bool segments_intersect(point p1,point p2,point p3,point p4)//判断线段相交 
{
	double d1=crossProduct(p1,p2,p3);
	double d2=crossProduct(p1,p2,p4);
	double d3=crossProduct(p3,p4,p1);
	double d4=crossProduct(p3,p4,p2);
	if(d1*d2<0 && d3*d4<0)
	{
		return true;
	}
	//d=0时为平行情况,此时需要考虑端点是否在线段上 
	else if(!d1 && on_segment(p3,p4,p1))
	{
		return true;
	}
	else if(!d2 && on_segment(p3,p4,p2))
	{
		return true;
	}
	else if(!d3 && on_segment(p1,p2,p3))
	{
		return true;
	}
	else if(!d4 && on_segment(p1,p2,p4))
	{
		return true;
	}
	else 
	{
		return false;
	}
}
bool inPoly(int n,point p1,point p[])//判断点是否在多边形内 
{
	int cnt;
	int i=0;
	p[0]=p[n]; 
	while(i<n)
	{
		p2.x=rand()+MAX; 
		p2.y=rand()+MAX;
		for(i=cnt=0;i<n;i++)
		{
			if(on_segment(p[i],p[i+1],p1))//点在边上 
			{
				return true;
			}
			else if(crossProduct(p1,p2,p[i])==0)//点在射线上,停止本循环,另取p2 
			{
				break;
			}
			else if(segments_intersect(p1,p2,p[i],p[i+1]))//射线与边相交,统计交点数 
			{
				cnt++;
			}
		}
	}
	if(cnt%2)
	{
		return true;
	}
	else
	{
		return false;
	}
}
int main()
{
	int n;
	while(cin>>n)
	{
		for(int i=1;i<=n;i++)
		{
			cin>>p[i].x>>p[i].y;
		}
		int m;
		cin>>m;
		while(m--)
		{
			cin>>p1.x>>p1.y;
			if(inPoly(n,p1,p))
			{
				cout<<"Yes"<<endl;
			}
			else
			{
				cout<<"No"<<endl;
			}
		}
	}
	system("pause");
	return 0;
}

晚上金山的复赛~

希望通过这一段时间的学习自己不要吃鸭蛋。。。

加了个油~


金山复赛第一场只做了一题。。。

第二场浮躁了。。。

一点也做不下去了。。。

今天把计算几何看了一点点。。

凸包什么的。。

模版


 题解:

hdu 1221:http://acm.hdu.edu.cn/showproblem.php?pid=1221

/*
分别判断矩形的四条边与圆的位置关系。。
没有思路。。
copy的discuss中的代码
学习。。
*/

/*
后来想了想。。
这题是基本题啊尼玛。。
矩形四边都是平行于坐标轴的。。。
。。。。。
*/
 
#include<iostream>
#include<cstdlib>
#include<cmath>
using namespace std;
struct point
{
    double x;
    double y;
};
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 major(point A,point B,point centre,double radius)
{
    double a,b,c;
    int flag;
    a=dis(centre,A),b=dis(centre,B);
    c=fabs(centre.y-A.y);
    if(centre.x<=A.x||centre.x>=B.x) //垂点在边线段外
    {
       if((a-radius)*(b-radius)<=0)
           flag=1;
       else
	   	   flag=0;
    }
    else //如果垂点在边线段上
     {
        if(c<=radius)
        {
            if(a>radius||b>radius)
                 flag=1;
            else 
				 flag=0;
        }
        else flag=0;
    }
    return flag;
}
int main()
{
    int t;
    cin>>t;
    while(t--)
    {
        point centre,A,B,C,D;
        double radius;
        cin>>centre.x>>centre.y>>radius;
        cin>>A.x>>A.y>>C.x>>C.y;
        B.x=C.x,B.y=A.y,D.x=A.x,D.y=C.y;
        double a,b,c;
        int flag_1,flag_2,flag_3,flag_4;  //1为相交,0为相离
        flag_1=major(A,B,centre,radius);
        flag_2=major(B,C,centre,radius);
        flag_3=major(C,D,centre,radius);
        flag_4=major(D,A,centre,radius);
        if(flag_1||flag_2||flag_3||flag_4)
        	cout<<"YES"<<endl;
        else 
			cout<<"NO"<<endl;
    }
}

hdu 1348: http://acm.hdu.edu.cn/showproblem.php?pid=1348

/*
凸包模版。。
不解释了。。
尼玛想改成纯c++代码wa了一万遍了。。。。。。
回头再看。
我想知道为什么sort不行啊啊啊啊啊 
*/ 
/*
刚刚分别打印排序后结果发现
尼玛排序顺序竟然刚好相反。。
原来qsort 中如果返回a>b意思是顺序输出。。
而sort 如果返回a>b意思就是逆序啊。。。。
。。。
学习了!!!
*/
 
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <iostream> 
#include <algorithm>
using namespace std;
const int N = 1005;
const double PI = 3.1415927;
struct point 
{
	double x;
    double y;
}p[N],stack[N];
 
double dis(point p1,point p2)
{
	return sqrt((p1.x-p2.x)*(p1.x-p2.x)+(p1.y-p2.y)*(p1.y-p2.y));
}
double crossProduct(point p1,point p2,point p)//判断点是否在直线两边 
{
	return (p.x-p1.x)*(p.y-p2.y)-(p.y-p1.y)*(p.x-p2.x);
}
 
 //以最左下的点为基准点,其他各点(逆时针方向)以极角从小到大的排序规则
bool cmp(const point &a, const point &b)
{
    double k=crossProduct(a,b,p[0]);//极角大小转化为求叉乘
    if (k<0 || !k && dis(p[0], a)>dis(p[0], b)) 
		return false;
    return true;
} 
double Graham(int n)
{
	double x = p[0].x;
    double 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;
            flag=i;
        }
    }
    swap(p[0],p[flag]);
    sort(p+1,p+n,cmp2);
    p[n]=p[0];
    stack[0]=p[0];
    stack[1]=p[1];
    stack[2]=p[2];
    int top=2;
    for(int i=3;i<=n;i++)
	{//加入一个点后,向右偏拐或共线,则上一个点不在凸包内,则--top,该过程直到不向右偏拐或没有三点共线的点 
		while(crossProduct(stack[top], p[i],stack[top-1])<=0 && top>=2) 
			--top;
        stack[++top]=p[i];//在当前情况下符合凸包的点,入栈
    }
    double len=0;
    for(int i=0;i<top;++i)
		len+=dis(stack[i],stack[i+1]);
    return len;
}
 
int main()
{
	int T;
    cin>>T;
	while(T--) 
	{
        int n,l;
        cin>>n>>l;
        for(int i=0;i<n;++i) 
		{
			cin>>p[i].x>>p[i].y;
		}
        double ans=Graham(n);
        ans+=PI*(l+l);
        printf("%.0lf\n",ans);
        if(T)
		{ 
			printf("\n");
        }
    }
    system("pause");
    return 0;
}

hdu 1392: http://acm.hdu.edu.cn/showproblem.php?pid=1392

/*
凸包模版。。
啊啊啊啊啊
好烦躁
*/
 

#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;
}

double 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];
    stack[0] = p[0];
    stack[1] = p[1];
    stack[2] = p[2];
    int top = 2;
    for (int i=3; i<=n; ++i) {//加入一个点后,向右偏拐或共线,则上一个点不在凸包内,则--top,该过程直到不向右偏拐或没有三点共线的点 
        while (crossProd(stack[top-1], stack[top], p[i])<=eps && top>=2) --top;
        stack[++top] = p[i];//在当前情况下符合凸包的点,入栈
    }
    double len = 0;
    for (int i=0; i<top; ++i) len += dis(stack[i], stack[i+1]);
    return len;
}

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.00\n");
        else if (n == 2) printf ("%.2lf\n", dis(p[0], p[1]));
        else {
            double len = Graham(n);
            printf ("%.2lf\n", len);
        }
    }
    return 0;
}

难过的,都过去吧。

坚持。

### C语言学习路径 为了成为百强级别的C语言程序员,需遵循一条系统的成长路线。这条路线不仅涵盖了基础知识的学习,还包括实践项目的积累和技术深度的理解。 #### 基础阶段:掌握核心概念 在这个阶段,重点应放在理解C语言的基础语法和特性上。这包括变量声明、数据类型、运算符、控制流语句(if/else, switch)、循环结构(for, while),以及函数定义与调用[^1]。 ```c #include <stdio.h> int main() { int a = 5; printf("Value of a is %d\n", a); return 0; } ``` #### 进阶阶段:深入探索高级主题 随着对基本概念的熟悉度增加,可以转向更复杂的话题,比如指针操作、内存管理、文件I/O处理、动态分配数组等。这些知识点对于编写高效可靠的程序至关重要[^2]。 ```c // 动态分配内存的例子 #include <stdlib.h> void* safe_malloc(size_t size){ void *ptr = malloc(size); if(ptr == NULL){ fprintf(stderr,"Out of memory"); exit(1); } return ptr; } ``` #### 实践应用:构建实际项目经验 理论知识固然重要,但真正的提升来自于动手做项目。可以选择参与开源项目贡献代码,或是自己发起一些小型的应用开发工作来锻炼解决问题的能力。通过不断尝试新的挑战,逐步建立起解决各种问题所需的技能集[^3]。 #### 技术深化:关注性能优化与安全编码 当具备了一定的经验之后,应该更加注重于如何写出高性能且安全性高的代码。了解编译器的工作原理可以帮助更好地利用底层资源;而学习常见的漏洞防范措施则能有效减少潜在风险[^4]。 ### 编程技巧 - **阅读优秀源码**:经常浏览高质量的开源库或工具包中的实现细节,从中汲取灵感。 - **练习算法题目**:定期参加在线竞赛平台上的刷题活动,强化逻辑思维能力。 - **保持好奇心**:积极跟踪行业最新趋势和发展方向,持续更新自己的知识体系。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值