ZOJ 3981 && 2017CCPC秦皇岛 A:Balloon Robot

来源:互联网 发布:rrt star算法 编辑:程序博客网 时间:2024/05/16 15:21

http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3981

题解

题意

第一行三个数字n, m, q表示有m个座位围成一个环,已知n个队伍,q次预测
第二行n个数表示n个队伍所在位置(1<=ai<=m)
接下来有q行,每行a, b表示预测到第ai的队伍在b时间需要插气球

有一个只会每一秒顺时针移动一个位置的发气球机器人(机器人中间不停止移动)。
只要当前队伍有题目已经A了就会给他对应数量的气球。如果a队伍在b时刻A了一道题,并在c时刻才拿到气球,那么这个队伍就会积累c-b点不开心值。
求一个机器人从起始位置(一开始是第0秒)开始移动,使得所有队伍最终不开心值之和最小。

题解

我们知道,对于每一次预测,一个队伍的不开心值w小于m,因为只会有两种情况,一种是当前圈内能完成发气球,另一种是下一个圈发气球,最多积累m-1不开心值。
假设我们起始位置是1,p为当前队伍所在下标,b为该队伍AC时间,所以得到该队伍不开心值的公式:w=(p-1-(b%m)+m)%m
例如:

2 3 3
1 2
1 1
2 1
1 4

则假设起始位置为1时,p次的怒气值为w[]:2 0 2
则假设起始位置为2时,p次的怒气值为w[]:1 2 1
则假设起始位置为3时,p次的怒气值为w[]:0 1 0
从怒气值数组变化看出,如果w[i]!=0时,则w[i]=w[i]-1,否则w[i]=0。
此时我们知道,只要找到w[i]序列和的最小值,因为每次w[i]变化都会不同,但只要排好序,时间复杂度只要O(q)。
排好序后,我们只要计算,在i前面的那些点减去i之后肯定是小于0的,此时就需要为这些点加上m,总共需要加上i*m,又所有点需要减去w[i],即q*w[i]。
最小值和即为答案。

C++代码

#include<stdio.h>#include<iostream>#include<algorithm>using namespace std;typedef long long LL;const int maxn=1e5+100;LL a[maxn],w[maxn];int main(){    //freopen("c:\\in.txt","r",stdin);    int T;    scanf("%lld",&T);    while(T--)    {        LL n,m,q;        scanf("%lld%lld%lld",&n,&m,&q);        LL sum=0;        for(int i=1;i<=n;i++)            scanf("%lld",&a[i]);        for(int i=0;i<q;i++)        {            LL a,b;            scanf("%lld%lld",&a,&b);            w[i]=(a[a]-1-(b%m)+m)%m;//求从起始位置开始计时到该点时的不开心值            sum+=w[i];        }        /*for(int i=0;i<q;i++){            cout<<w[i]<<" ";        }cout<<endl;*/        sort(w,w+q);//排序        LL ans=1e18;        for(int i=0;i<q;i++){                    ans=min(ans,(sum+i*m-q*w[i]));//对于0-i位置加m再减掉q*w[i]        }        printf("%lld\n",ans);    }    return 0;}
原创粉丝点击