ZOJ 3981 Balloon Robot

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

题意:

现在有n只队伍分布在m张桌子上(每个队伍在一张桌子上),现在有一个送气球的机器人,初始位置可以是这m个桌子的任意一个,机器人沿着顺时针方向沿着桌子走,如果机器人所在位置有队伍A了题目,机器人就会送上气球。现在如果某个队伍在Ta时刻A了题目,然后气球在Tb时刻被送到,那么此时的不开心值就有Tb-Ta。现在要使所有队伍的不开心值总和最小,问机器人一开始应该位于哪里。

思路:

现在假设机器人位于1号桌子处:

5个A题点需要等待的时间分别为 2 0 1 0 2。

如果初始机器人位于2号桌子处,那么需要等待的时间分别为 1 2 0 2 1。

可以发现,当机器人向右移动时,每个点等待的时间变为(t-1+m)%m。

但是对于每一个位置,你不可能去修改每个点的等待时间,这样时间复杂度太高了。

我们可以先计算出机器人位于1桌子时每个点的等待时间,然后排序,假设为d[i],对于d[i]来说,如果要让该点的等待时间为0,那么需要机器人向右移动d[i]个桌子,其余各点也就都需要减去d[i],由于已经按照时间排好了序,所以在i前面的那些点减去i之后肯定是小于0的,此时就需要为这些点加上m,总共需要加上i*m,所有点需要减去d[i],即q*d[i]。

 1 #include<iostream>
 2 #include<algorithm>
 3 #include<cstring>
 4 #include<cstdio>
 5 #include<vector>
 6 #include<stack>
 7 #include<queue>
 8 #include<cmath>
 9 #include<map>
10 #include<set>
11 using namespace std;
12 typedef long long ll;
13 typedef pair<int,int> pll;
14 const int INF = 0x3f3f3f3f;
15 const int maxn = 1e5+5;
16 
17 ll n, m, q;
18 ll p[maxn], d[maxn];
19 
20 int main()
21 {
22    //freopen("in.txt","r",stdin);
23    int T;
24    scanf("%d",&T);
25    while(T--)
26    {
27        scanf("%lld%lld%lld",&n,&m,&q);
28        for(int i=0;i<n;i++)  scanf("%d",&p[i]);
29 
30        ll sum = 0;
31        for(int i=0,j;i<q;i++)
32        {
33            ll t;
34            scanf("%d%lld",&j,&t);
35            d[i]=(p[j-1]-1-t%m+m)%m;
36            sum=sum+d[i];
37        }
38        ll ans = (ll)1e18;
39        sort(d,d+q);
40        for(int i=0;i<q;i++)
41        {
42            if(i==0 || d[i]!=d[i-1])
43            {
44                ans = min(ans, sum + i*m - q*d[i]);
45            }
46        }
47        cout<<ans<<endl;
48    }
49    return 0;
50 }
原文地址:https://www.cnblogs.com/zyb993963526/p/7763983.html