1. 程式人生 > >【推導】zoj3981 Balloon Robot

【推導】zoj3981 Balloon Robot

順時針 mes 這樣的 需求 存在 urn src using 距離

題意:一個桌子有m個位置(首尾相接),有n支隊伍坐在其中的n個位置上。有個機器人會從某個起始位置出發,每個時刻會依次發生以下三個事件:

機器人順時針轉一個單位;

某些隊伍通過了題目(如果存在);

如果機器人的當前的位置的隊伍需求氣球,機器人就會把他需求的氣球都給他。

讓你對於所有可能的初始位置,最小化所有隊伍的所有題目的氣球等待時長之和。

設一個函數y軸是等待時間,x軸是機器人的初始位置,於是每道題恰好被分成了兩個斜率為-1的一次函數。

假設某道題目是在ci時刻由bi位置的隊伍通過的,y=(bi-(x+ci)%m+m)%m

最小化每個位置所有函數圖像到x軸的距離之和。

只需要枚舉每個一次函數與x軸的交點,嘗試用當前位置的值更新答案。

技術分享

單題的函數畫出來是這樣的。

#include<algorithm>
#include<cstdio>
using namespace std;
typedef long long ll;
ll ans,sum;
int n,m,K,T,s[100005],b[100005],c[100005],x[100005];
int main(){
    scanf("%d",&T);
    for(;T;--T){
        ans=sum=0;
        scanf("%d%d%d",&n,&m,&K);
        for(int i=1;i<=n;++i){
            scanf("%d",&s[i]); --s[i];
        }
        for(int i=1;i<=K;++i){
            scanf("%d%d",&b[i],&c[i]);
            b[i]=s[b[i]];
        }
        for(int i=1;i<=K;++i){
            x[i]=(b[i]-c[i]%m+m)%m;
            sum+=(ll)x[i];
        }
        sort(x+1,x+K+1);
        ans=sum;
        for(int i=1;i<=K;++i){
            sum-=(ll)(x[i]-x[i-1])*(ll)K;
            ans=min(ans,sum);
            sum+=(ll)m;
        }
        printf("%lld\n",ans);
    }
    return 0;
}

【推導】zoj3981 Balloon Robot