1 条题解

  • 0
    @ 2021-07-22 17:50:11

    40%就不说了,直接模拟。

    80%的数据,\(n\)非常小,\(m\)很大,这意味着我们可以直接跳到下一次发生冲突的时间去,而不是一秒一秒地模拟机器人的行为。
    \(O(n^2)\)可以判断最近一次的冲突发生时间,然后进行删除和记录。所以整个算法的复杂度是\(O(n^3)\)

    到这一步还是相对容易的。

    注意判断两个机器人相撞时间的函数,分四类情况讨论。

    int cal(robot &r1, robot &r2)
    {
        if((r2.loc - r1.loc)%2 == 1) return 99999999;
        if(r1.vel == 'R' && r2.vel == 'R') return (2 * m - r1.loc - r2.loc) / 2; 
        if(r1.vel == 'L' && r2.vel == 'L') return (r1.loc + r2.loc) / 2;
        if(r1.vel == 'R' && r2.vel == 'L') return (r2.loc - r1.loc) / 2; 
        if(r1.vel == 'L' && r2.vel == 'R') return (2 * m - (r2.loc - r1.loc)) / 2;
    } 
    

    其他的代码如下:

    #include<bits/stdc++.h>
    using namespace std;
    
    //Header
    struct robot{
        int loc;
        int index; 
        char vel;
    };
    
    int n,m; 
    
    void solve()
    {
        cin>>n>>m;
        robot a[n];
        for(robot &i: a) cin>> i.loc;
        for(robot &i: a) cin>> i.vel;
        
        int b[n];
        for(int i = 0; i < n; i++) b[i] = -1, a[i].index = i; 
        
        while(1)
        {
            int minv = 99999999, loc1 = 1, loc2 = 1;
            for(int i = 0; i < n; i++)
            {   
                for(int j = i + 1; j < n; j++)
                {
                    if(cal(a[i], a[j]) < minv)
                    {
                        minv = cal(a[i], a[j]); // 求最近的碰撞事件
                        loc1 = i;
                        loc2 = j;
                    }
                }
            }
            if(minv == 99999999) break;
            b[a[loc1].index] = b[a[loc2].index] = cal(a[loc1], a[loc2]);
            for(int i = loc1; i < n-1; i++) a[i] = a[i+1];
            n--;
            for(int i = loc2-1; i < n-1; i++) a[i] = a[i+1];
            n--; //数组的删除,既然两个机器人碰撞, 则删去它们。
        } 
        for(int i: b) cout<<i<<" "; 
    }
    
    int main()
    {   
        solve();
        return 0;
    }
    

    对于\(100\%\)的数据,只能考虑线性的做法。容易发现位于奇数的机器人和位于偶数的机器人永远不会相撞,我们分别考虑。

    比如对于奇数,我们考虑模拟"栈"的操作,从左到右加入一个个机器人。那么,我们考虑"LL","LR","RL","RR"四种相撞:

    一旦当前是"R"而即将读入"L","R"一定与"L"碰撞而不是其他机器人,所以立即计算它们的碰撞时间,然后弹出它们。
    若当前是"L"而即将读入"L",与即将读入的"L"碰撞一定比之后的要好。所以"LL"也是立即匹配,并弹出。

    第一轮处理的时候,先不要考虑"RR"的匹配,因为若后面可能再出现"L","RL"是优先碰撞的。

    操作过后,栈的最底部至多有一个"L",之后全部是"R"。这样的话,应当先让"RR"进行匹配,"LR"留到最后匹配。

    Code:

    #include<bits/stdc++.h>
    using namespace std;
    
    //Header
    struct robot{
        int loc;
        int index; 
        char vel;
    };
    
    int n,m; 
    int cal(robot &r1, robot &r2)
    {
        if((r2.loc - r1.loc)%2 == 1) return 99999999;
        if(r1.vel == 'R' && r2.vel == 'R') return (2 * m - r1.loc - r2.loc) / 2; 
        if(r1.vel == 'L' && r2.vel == 'L') return (r1.loc + r2.loc) / 2;
        if(r1.vel == 'R' && r2.vel == 'L') return (r2.loc - r1.loc) / 2; 
        if(r1.vel == 'L' && r2.vel == 'R') return (2 * m - (r2.loc - r1.loc)) / 2;
    } 
    
    void solve()
    {
        cin>>n>>m;
        robot a[n];
        for(robot &i: a) cin >> i.loc;
        for(robot &i: a) cin >> i.vel;
        
        int b[n];
        for(int i = 0; i < n; i++) b[i] = -1, a[i].index = i; 
        
        vector<robot> v[2];//分成奇偶 
        for(robot i: a) v[i.loc%2].push_back(i);
        
        //以上是准备工作 
         
        for(int i = 0; i <= 1; i++)
        {
            vector<robot> tmp;
            for(robot it: v[i])
            {
                int siz = tmp.size();
                if(siz == 0) 
                {
                    tmp.push_back(it); 
                    continue;
                }
                
                if(it.vel == 'L') // LL, RL
                {
                    b[tmp[siz-1].index] = b[it.index] = cal(tmp[siz-1], it);
                    tmp.pop_back();
                }
                else tmp.push_back(it);
            }
            while(tmp.size()>1)
            {
                int siz = tmp.size();
                if(tmp[siz-1].vel == 'R') //RR, LR
                {
                    b[tmp[siz-1].index] = b[tmp[siz-2].index] = cal(tmp[siz-2], tmp[siz-1]);
                    tmp.pop_back(); tmp.pop_back();
                }
            }
        }  
        for(int i: b) cout<<i<<" "; 
    }
    
    int main()
    {   
        solve();
        return 0;
    }
    
  • 1

信息

ID
1287
难度
8
分类
(无)
标签
(无)
递交数
41
已通过
6
通过率
15%
被复制
4
上传者