201803-2 CCF 碰撞的小球----优先队列(满分实现)

CCF201803-2 CCF 碰撞的小球----优先队列实现

原题题目
在这里插入图片描述
在这里插入图片描述
题目中图示特别说明的一点就是小球碰撞的时候并不是真实碰撞,而是将其视为一个质点,其碰撞时的自身距离忽略不计
另外示例2表示输入小球的位置不一定按照顺序输入。因此若要暴力确定小球之间是否碰撞,复杂度为:O(n²)。若小球位置是有次序的,则只需要比较相邻两个小球的距离差,花费O(n)线性复杂度则可以完成。因此此处我们特别用优先队列对其位置进行排序,O(nlogn)。
程序总体时间复杂度为O(nlogn)
而输出要求则是按照输入顺序进行输出。因此我们需要用结构体一共保存三个重要变量小球运动方向,小球当前位置和小球输入顺序。
刚开始输入时,输入序列为小球位置无序,但小球输入顺序有序。
进行处理时为小球位置有序,小球输入顺序无序。
而最终我们重新对小球进行排序,让其变成小球位置无序,小球输入顺序有序的状态

#include<iostream>
#include<queue>
using namespace std;

struct state{
	int pos;
	int dir=1;
	int start_index=-1;
};


struct cmp{
	bool operator()(state x,state y)
	{
		return x.pos>y.pos;
	}
};

struct cmpIndex{
	bool operator()(state x,state y)
	{
		return x.start_index>y.start_index;
	}
};

const int MAX_N=1000;



state left_pos;
state right_pos;

int end_time;

void swap(int &n1,int &n2)
{
	int t=n1;
	n1=n2;
	n2=t;
}

void display(priority_queue<state,vector<state>,cmpIndex> &q2,int n)
{
	for(int i=0;i<n;i++){
		cout<<q2.top().pos<<" ";
		q2.pop();
	}	
	
	
}

void updatePos(state pos[MAX_N],int n)
{
	for(int i=0;i<n;i++){
		pos[i].pos+=pos[i].dir;
	}
}

void IsEdge(state pos[MAX_N],int n)
{
	for(int i=0;i<n;i++){
		if(pos[i].pos==left_pos.pos){
			pos[i].dir=1;
		}
		else if(pos[i].pos==right_pos.pos){
			pos[i].dir=-1;
		}
		
	}
}

void IsColl(state pos[MAX_N],int n)
{
	for(int i=0;i<n-1;i++){
		if(pos[i].pos==pos[i+1].pos){
			swap(pos[i].dir,pos[i+1].dir);
		}
		
	}
}

void Try(int now_t,state pos[MAX_N],int n)
{
	if(now_t==end_time){
		return;
	}
	
	updatePos(pos,n);
	IsEdge(pos,n);
	IsColl(pos,n);
	
	Try(now_t+1,pos,n);
	
}

void initEdgePos(int L)
{
	left_pos.dir=-1;
	left_pos.pos=0;
	
	right_pos.dir=1;
	right_pos.pos=L;
}

void input(priority_queue<state,vector<state>,cmp> &q,int n)
{
	for(int i=0;i<n;i++){
		state temp;
		cin>>temp.pos;
		temp.start_index=i;
		q.push(temp);
	}
}

void SortByPos(priority_queue<state,vector<state>,cmp> &q,int n,int L,state start_pos[MAX_N])
{
	for(int i=0;i<n;i++){
		state temp;
		temp.pos=q.top().pos;
		temp.start_index=q.top().start_index;
		
		start_pos[i].pos=temp.pos;
		start_pos[i].start_index=temp.start_index;
		
		q.pop();
		
		if(temp.pos==L){
			start_pos[i].dir=-1;
		}
	}
}

void SortByIndex(priority_queue<state,vector<state>,cmpIndex> &q2,int n,state start_pos[MAX_N])
{
	for(int i=0;i<n;i++){
		q2.push(start_pos[i]);
	}
}

int main()
{
	int n,L,t;
	cin>>n>>L>>t;
	
	priority_queue<state,vector<state>,cmp> q;//将位置进行排序 
	priority_queue<state,vector<state>,cmpIndex> q2;//按照输入的次序进行排序 
	
	end_time=t;
	
	int startPos[MAX_N];
	state start_pos[MAX_N];
	
	initEdgePos(L);
	
	input(q,n);
	
	SortByPos(q,n,L,start_pos);
	
	Try(0,start_pos,n);
	
	SortByIndex(q2,n,start_pos);
	
	
	display(q2,n);
	
	return 0;
} 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值