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