最近都在写LightOj的东西 ~ 昨天也是以LightOj为主写了两个题目。题解什么的今天晚些时候应该会更新 ~
下午的时间本来是用于看统计学习方法的一些东西xD,但是今天周天,实验室里人也很少,兴趣寥寥,就找了场div2 写写练手,coding的感觉在最近慢慢有点回复上来,毕竟回到学校也有将近一周的时间了,不好好调整是不可以的。div1后面也会慢慢写,这也是当初答应楠妹妹的事儿xD。
(一) 250 poi
第一题的话,是模拟题,题意大概就是,给你一个10进制的数,将其转化成16进制,如果其中有1-9那么则说明转化非法,否则用I代替1,其余表示不变化,输出这个16进制数值。因此就直接贴贴代码
string decode(long long ciphertext) {
int ret[100005];
memset(ret,0,sizeof(ret));
int cnt=0;
long long n=ciphertext;
while (n!=0){
ret[cnt++]=n%16;
n=n/16;
}
string fin="";
bool flag=true;
for (int i=cnt-1;i>=0;i--){
if (ret[i]>=10)
fin=fin+char('A'+ret[i]-10);
else if (ret[i]==1)
fin=fin+'I';
else if (ret[i]==0)
fin=fin+'O';
else{
flag=false;
break;
}
}
if (flag)
return (fin);
return ("Error!");
}
是一题构造题,要求构造出节点数为n其中叶节点数为m的树。
一开始看前几个example都是二叉树的样子,认为是二叉树,后来又看了题目只是说明tree之后,就比较好构造了。
主要采取的办法就是,首先将m-1个节点同某个节点相连,之后以链状链接之后的节点就可以了。下图说明了n=6 m=3的情况
其实 这样的话将m-1个节点连在同一个节点上时,也就为之后的链子的另一端预留出了一个叶节点,如果m=n-1的话 自然会形成一个星型结构,另一段也会由一条链退化为点,总之就是挑了好写的构造来写
vector <int> getTree(int n, int m) {
vector <int> ret;
ret.clear();
int tmp_r=n-m+1;
for (int i=n;i>tmp_r;i--){
ret.push_back(i-1);
ret.push_back(tmp_r-1);
}
for (int i=tmp_r-1;i>=1;i--){
ret.push_back(i);
ret.push_back(i-1);
}
return(ret);
}
(三) 1000 poi
题意大概是:给你少于等于3个点点上有卫兵,点的坐标范围在-1000~1000之间,你初始状态在原点,你为了达到(10^100,0)这个点你可以走任何的曲线,对于任意一条曲线卫兵到它的最短距离为d,求存在的最大的d是多少。
这题算是一道简单的计算几何题目吧? 我个人觉得应该算,也是我不怎么会写的题型之一了吧? 这一题一开始思考了某种思路:
1.如果点数小于3的话,其实我们初始状态下里的最近的点就是最终的d,因为两个点在平面内不能组成封闭的图形,你可以采取很多种策略绕过这两个点到达(10^100,0)也就是说你至少可以使任意时刻的距离大于初始状态下离卫兵的最小距离。
2.如果有三个点,就要分类:
2.1 如果初始点并不在三角形内,那么最终的结果应该和小于3个点的情况相同,因为不被封闭因此你至少可以使任意时刻的距离大于初始状态下离卫兵的最小距离。
2.2 如果初始点在三角形内,我们首先考虑如果要出三角形,就肯定要经过某条边,因此最终的d肯定是小于等于三条边中最长那条边的1/2的,当然最终的d也会小等于初始状态下离卫兵的最小距离。
那中间状态呢? 我们考虑一个这样的策略:
在任一时刻,距离三点的距离为d1,d2,d3 我们这个瞬间走的方向是最短距离对应点的反方向。
因此下个时刻离卫兵的最小距离肯定大等于前一个时刻。直到走到三角形的外心为止。
走到外心之后(如果还在三角形内)沿着最长边对应的那条垂直平分线走。因为如果要离开三角形则必须经过边,该垂直平分线上的任意一点到两端的距离都要比最长边的1/2来的长,因此肯定是优于走出三角形瞬间据离卫兵的最短距离的。下面将以图说明:
绿点是当前位置,黄色方向为当前行走方向。蓝色点为外心点。棕色线是到达外心之后的行走方向。
这样一个决策被我把第一个大点直接忘记了Q+Q。 后面要判断在三角形内的话有应用到叉积的知识。 叉积在用于判断同侧异侧的时候很方便另外说明一下二维坐标向量(x1,x2),(y1,y2)叉积是x1y2-x2y1 这个值的正负性质是我们判断同侧异侧的重点。 下图说明:
然后贴代码xD
double maximalSafetyLevel(vector <int> x, vector <int> y) {
int n=x.size();
double ret=-1.0;
if (n==1 || n==2){
for (int i=0;i<n;i++){
double dis=double(sqrt(double(x[i]*x[i]+y[i]*y[i])));
if (ret<0 || dis<ret)
ret=dis;
}
return (ret);
}
double dis_a=double(sqrt(double(x[0]*x[0]+y[0]*y[0])));
double dis_b=double(sqrt(double(x[1]*x[1]+y[1]*y[1])));
double dis_c=double(sqrt(double(x[2]*x[2]+y[2]*y[2])));
double dis_fi=min(dis_a,min(dis_b,dis_c));
bool flag=true;
for (int i=0;i<3;i++){
int node1=(i+1)%3;
int node2=(i+2)%3;
double vec_x1=(x[node2]-x[node1])*(-y[node1])-(y[node2]-y[node1])*(-x[node1]);
double vec_x2=(x[node2]-x[node1])*(y[i]-y[node1])-(y[node2]-y[node1])*(x[i]-x[node1]);
//printf("test_node %d ----> edge %d_%d vec1:%lf vec2:%lf\n",i,node1,node2,vec_x1,vec_x2);
if (vec_x1*vec_x2<=0)
flag=false;
}
if (flag){
double dis_se=-1.0;
for (int i=0;i<3;i++)
for (int j=i+1;j<3;j++){
double x_t=(x[i]-x[j]);
double y_t=(y[i]-y[j]);
dis_se=max(dis_se,double(sqrt(double(x_t*x_t+y_t*y_t)))/2.0);
}
ret=min(dis_fi,dis_se);
return (ret);
}
else
return (dis_fi);
}
嗯 这样div2 就基本完成了,最近因为对自己说的是恢复状态,就写写相对简单的题目,不过调整好了之后就没什么借口了呢~无论如何还是要加油xD 今天去吃KFC好高兴