poj 2991 (线段树+数学)

本文介绍了一道关于模拟起重机运动的编程题,通过线段树数据结构优化计算过程。详细解析了如何利用线段树维护旋转角度,并计算末端坐标。

Crane

Time Limit: 2000MS Memory Limit: 65536K
Total Submissions: 9336 Accepted: 2476 Special Judge

Description

ACM has bought a new crane (crane -- jeřáb) . The crane consists of n segments of various lengths, connected by flexible joints. The end of the i-th segment is joined to the beginning of the i + 1-th one, for 1 ≤ i < n. The beginning of the first segment is fixed at point with coordinates (0, 0) and its end at point with coordinates (0, w), where w is the length of the first segment. All of the segments lie always in one plane, and the joints allow arbitrary rotation in that plane. After series of unpleasant accidents, it was decided that software that controls the crane must contain a piece of code that constantly checks the position of the end of crane, and stops the crane if a collision should happen. 

Your task is to write a part of this software that determines the position of the end of the n-th segment after each command. The state of the crane is determined by the angles between consecutive segments. Initially, all of the angles are straight, i.e., 180o. The operator issues commands that change the angle in exactly one joint. 

Input

The input consists of several instances, separated by single empty lines. 

The first line of each instance consists of two integers 1 ≤ n ≤10 000 and c 0 separated by a single space -- the number of segments of the crane and the number of commands. The second line consists of n integers l1,..., ln (1 li 100) separated by single spaces. The length of the i-th segment of the crane is li. The following c lines specify the commands of the operator. Each line describing the command consists of two integers s and a (1 ≤ s < n, 0 ≤ a ≤ 359) separated by a single space -- the order to change the angle between the s-th and the s + 1-th segment to a degrees (the angle is measured counterclockwise from the s-th to the s + 1-th segment).

Output

The output for each instance consists of c lines. The i-th of the lines consists of two rational numbers x and y separated by a single space -- the coordinates of the end of the n-th segment after the i-th command, rounded to two digits after the decimal point. 

The outputs for each two consecutive instances must be separated by a single empty line.

Sample Input

2 1
10 5
1 90

3 2
5 5 5
1 270
2 90

Sample Output

5.00 10.00

-10.00 5.00
-5.00 10.00

题意:有n根长度不尽相同的棍子,初始时它们首尾垂直相连,标号为1--n,第一根棍子的下端坐标为(0,0),上端坐标为(0,len[1]),其余棍子依次类推。接下来执行C此旋转,每次输入一个编号num和角度rad,使得第num根棍子和第num+1跟棍子间的逆时针角度变为rad度(开始因为这里WA了好几次,因为我理解成第num+1棍子相对于num顺时针旋转了rad度..),求每次旋转后第n跟棍子端点的坐标。
题解:记录第num根棍子和第num+1跟棍子间的逆时针角度pre[num],这样每次输入rad时就能确定第num+1根及以后棍子的绝对旋转角度,然后用这个角度维护区间值。对于一个向量(x,y),它顺时针旋转A度后,得到的新向量为:x' = x * cos(A) + y * sin(A); y' = y * cos(A) - x * sin(A);
 

 

这个线段树tree存的每根棍子的端点坐标 不是叶子节点 其实对于每个改变对下面的棍子是没有影响的所以可以用线段树写这题

x/pi=angle/180  角度与弧度的换算

还有求转动的角度:链接

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<cmath>
#include<cstdlib>
#include<algorithm>
using namespace std;
const int N=10010;
const double pi=acos(-1.0);
struct node
{
	double x,y;
}tree[N<<2];
int lazy[N<<2];
int angle[N];
//转到a角度后 求坐标 
void rolate(int a,int k)
{
	double x=tree[k].x;
	double y=tree[k].y;
	double ang=pi/180*a;
	tree[k].x=cos(ang)*x-sin(ang)*y;
	tree[k].y=sin(ang)*x+cos(ang)*y;
}
void build(int l,int r,int k)
{
	if(l==r){
		scanf("%lf",&tree[k].y);
		tree[k].x=0;
		return;
	}
	int m=(l+r)>>1;
	build(l,m,k<<1);
	build(m+1,r,k<<1|1);
	tree[k].x=tree[k<<1].x+tree[k<<1|1].x;
	tree[k].y=tree[k<<1].y+tree[k<<1|1].y;
}

void push_down(int k)
{
	if(lazy[k]){
		rolate(lazy[k],k<<1);
		rolate(lazy[k],k<<1|1);
		lazy[k<<1]+=lazy[k];
		lazy[k<<1|1]+=lazy[k];
		lazy[k]=0;
	}
}
void update(int a,int x,int y,int l,int r,int k)
{
	if(x<=l&&y>=r){
		lazy[k]+=a;
		rolate(a,k);
		return;
	}
	push_down(k);
	int m=(l+r)>>1;
	if(x<=m) update(a,x,y,l,m,k<<1);
	if(y>m)  update(a,x,y,m+1,r,k<<1|1);
	tree[k].x=tree[k<<1].x+tree[k<<1|1].x;
	tree[k].y=tree[k<<1].y+tree[k<<1|1].y;
}
int main()
{
	int n,m;
	int cnt=0;
	while(scanf("%d %d",&n,&m)==2){
		if(cnt++) puts("");
		build(1,n,1);
		for(int i=1;i<=n;i++) angle[i]=180;
		memset(lazy,0,sizeof(lazy));
		while(m--){
			int s,a;
			scanf("%d %d",&s,&a);
			//注意:这个 angle代表的意思是 num0与num1相互有多少角度 
			int x=a-angle[s];//这样求出就是一个负数  对于顺时针求x“ y”是正确的 
			update(x,s+1,n,1,n,1);
			angle[s]=a;
			printf("%.2lf %.2lf\n",tree[1].x,tree[1].y);
		}
		
	}
	return 0;
}

 

【完美复现】面向配电网韧性提升的移动储能预布局与动态调度策略【IEEE33节点】(Matlab代码实现)内容概要:本文介绍了基于IEEE33节点的配电网韧性提升方法,重点研究了移动储能系统的预布局与动态调度策略。通过Matlab代码实现,提出了一种结合预配置和动态调度的两阶段优化模型,旨在应对电网故障或极端事件时快速恢复供电能力。文中采用了多种智能优化算法(如PSO、MPSO、TACPSO、SOA、GA等)进行对比分析,验证所提策略的有效性和优越性。研究不仅关注移动储能单元的初始部署位置,还深入探讨其在故障发生后的动态路径规划与电力支援过程,从而全面提升配电网的韧性水平。; 适合人群:具备电力系统基础知识和Matlab编程能力的研究生、科研人员及从事智能电网、能源系统优化等相关领域的工程技术人员。; 使用场景及目标:①用于科研复现,特别是IEEE顶刊或SCI一区论文中关于配电网韧性、应急电源调度的研究;②支撑电力系统在灾害或故障条件下的恢复力优化设计,提升实际电网应对突发事件的能力;③为移动储能系统在智能配电网中的应用提供理论依据和技术支持。; 阅读建议:建议读者结合提供的Matlab代码逐模块分析,重点关注目标函数建模、约束条件设置以及智能算法的实现细节。同时推荐参考文中提及的MPS预配置与动态调度上下两部分,系统掌握完整的技术路线,并可通过替换不同算法或测试系统进一步拓展研究。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值