2017 United Kingdom and Ireland Programming Contest (UKIEPC 2017)
H
题意:
有K个人进行跑步比赛。有两条要求:
1,所有人,两两之间的距离不得低于B否则会迷路
2,每个人不希望他人靠近自己Ai之内的距离
给出了p个路径点di,以及每个人现在所处的位置
求每次让谁跑到下一个路径点,不可能输出impossible
思路:
用队列维护这样一个数据结构:
结构内存储区间内当前状态下可以移动的人分别有哪些。
每次从队列里面取出一个人进行移动,此时队伍状态发生变化,显然,这只对取出的那个人的前一个人、后一个人,还有他本身产生影响,所以,动态维护的时候只需要判断这三个人是否符合条件,然后加进去就好了。要注意的是,数据结构内不允许一个人重复出现,所以需要用vis数组判重。
其他细节见代码
代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
inline long long read()
{
long long kk=0,f=1;
char cc=getchar();
while(cc<'0'||cc>'9'){if(cc=='-')f=-1;cc=getchar();}
while(cc>='0'&&cc<='9'){kk=(kk<<1)+(kk<<3)+cc-'0';cc=getchar();}
return kk*f;
}
int mark[1011];int B,P,K;
struct zj
{
int pos,dis,o;
};
zj an[1011];
bool cmp(zj a,zj b)
{
return a.pos<b.pos;
}
queue<int>q;int ans[1000011],co=0;bool vis[1000011];
bool check(int i)
{
int now,per,next;
now=an[i].pos;per=an[i-1].pos;next=an[i+1].pos;
if(now>=P)return 0;
if(i>1&&mark[now+1]-mark[per]>B)return 0;//往前走后不能让后面的人落下你太多 ,最后面的人没有后面
if(i<K&&next!=P)//最前面的人没有前面
if(mark[next]-mark[now+1]<max(an[i].dis,an[i+1].dis))return 0;//还要与前面的人保持距离
return 1;
}
int main()
{
B=read();P=read();
for(int i=1;i<=P;++i)mark[i]=read();
sort(mark+1,mark+1+P);//按照初始位置排序
K=read();
for(int i=1;i<=K;++i)
{
an[i].dis=read();an[i].o=i;
an[i].pos=read();
}
sort(an+1,an+1+K,cmp);
for(int i=1;i<=K;++i)
if(check(i))
{
if(!vis[i])q.push(i);vis[i]=1;//vis记录是否再队列中
}
int tot=0;
while(!q.empty())//移动每一个可移动的,同时维护他以及他前后的人是否可以移动
{
int now1=q.front();q.pop();ans[++co]=now1;//ans记录每次移动的方案
an[now1].pos++;
vis[now1]=0;
if(an[now1].pos==P)K--;//如果有人移动到终点,在区间内的人就少一,领队改变
if(K<=1)break;//考虑最后只剩下一个人的情况,接下
if(check(now1)&&!vis[now1])
{
q.push(now1);vis[now1]=1;
}
if(now1>1)
if(check(now1-1)&&!vis[now1-1])
{
q.push(now1-1);vis[now1-1]=1;
}
if(now1<K)
if(check(now1+1)&&!vis[now1+1])
{
q.push(now1+1);vis[now1+1]=1;
}
}
if(K>1)printf("impossible");//如果有不止一个人在区间内,但是维护的队列里没有元素,说明陷入死局
else
{
for(int i=1;i<=co;++i)printf("%d ",ans[i]);
while(++an[1].pos<=P)printf("%d ",an[1].o);//接上,一个人到达终点
}
return 0;
}
I
题意:
给出n个Hi ,1个T。求出T%Hi最小的那个Hi
思路:
循环一遍即可。
代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
inline long long read()
{
long long kk=0,f=1;
char cc=getchar();
while(cc<'0'||cc>'9'){if(cc=='-')f=-1;cc=getchar();}
while(cc>='0'&&cc<='9'){kk=(kk<<1)+(kk<<3)+cc-'0';cc=getchar();}
return kk*f;
}
LL a[20];
int main()
{
LL n=read();
for (int i=1;i<=n;i++)a[i]=read();
LL sum=read();
LL asd=a[1];
for (int i=2;i<=n;i++)if(sum%a[i]<sum%asd)asd=a[i];
printf("%d\n",asd);
}
j
题意:给出n个数,按照表格对应音符的长度,求曲子的总长度
思路:
可以看到,输入的数和音符的长度是倒数关系,用double存好后相加就好。要注意,输出一定要按6位输出…我就是这里没看到写炸了3次
代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
inline long long read()
{
long long kk=0,f=1;
char cc=getchar();
while(cc<'0'||cc>'9'){if(cc=='-')f=-1;cc=getchar();}
while(cc>='0'&&cc<='9'){kk=(kk<<1)+(kk<<3)+cc-'0';cc=getchar();}
return kk*f;
}
int main()
{
LL n=read();
double k,sum=0;
for(int i=1;i<=n;++i)
{
double kk=(double)(read());if(kk==0)k=2;
else k=((double)(1)/kk);
sum+=k;
}
printf("%.6llf",sum);
}