• Educational Codeforces Round 109 (Rated for Div. 2)(C,D)


    C-Robot Collisions

    题意:
    (0~m) 的坐标轴上,机器人在碰到边界时会反向继续行走,已知(n)个机器人的初始位置和初始方向,每个机器人的速度为(1),问每个机器人在哪个时刻爆炸,机器人爆炸当且仅当两个机器人在整数点相遇。
    思路:

    • 首先可以观察到只有机器人的初始位置的坐标的奇偶性相同时,才有可能发生碰撞,那么把问题分成两部分,奇坐标和偶坐标。
    • 对于某一可能碰撞部分,先将机器人按初始坐标排序,我们分两方面考虑,一方面是不需要转向的,对于不需要转向的,只有一种可能,即左边的向右边行走,右边的向左边行走。对于这一部分,我们可以用栈来维护,即向右边走的入栈,遇到向左边走的出栈,这样就可以保证正确性。
    • 另一方面,我们对于剩余的方向的(L)和方向为(R)的机器人,我们分别遍历,设(pos1<pos2),对于(L),我们按坐标从小到大遍历,对于相邻的两个机器人,其碰撞时刻一定是(pos1+(pos2-pos1)/2),对于(R),我们按坐标从大到小遍历,对于相邻的两个机器人,其碰撞时刻一定是(m-pos2+(pos2-pos1)/2)
    • 最后,方向(L)和方向(R)剩下的机器人最多都为(1),当两个都为(1)是,可以通过两个机器人都碰到边界后进行碰撞.

    代码:

    #include<bits/stdc++.h>
    using namespace std;
    const int MAXN=300001;
    const int INF=0x3f3f3f3f;
    
    int n,m;
    int a[MAXN];
    int ans[MAXN];
    map<int,int>mp;
    char cc[MAXN];
    struct node{
        int pos,dir;
    }s[MAXN];
    bool cmp(node xx,node yy)
    {
        return xx.pos<yy.pos;
    }
    vector<node>v[2];
    int main()
    {
        int T;
        cin>>T;
        while(T--){
            v[0].clear();
            v[1].clear();
            mp.clear();
            scanf("%d%d",&n,&m);
            for(int i=1;i<=n;i++){
                scanf("%d",&a[i]);
                mp[a[i]]=i;
                ans[i]=-1;
            }
            for(int i=1;i<=n;i++){
                getchar();
                scanf("%c",&cc[i]);
                v[a[i]%2].push_back((node){a[i],cc[i]=='L'});
            }
            for(int i=0;i<=1;i++){
                sort(v[i].begin(),v[i].end(),cmp);
                int cnt=0;
                for(int j=0;j<v[i].size();j++){
                    if(v[i][j].dir==0)s[++cnt]=v[i][j];
                    else{
                        if(cnt>0){
                            //cout<<i<<" "<<mp[s[cnt].pos]<<" "<<mp[v[i][j].pos]<<endl;
                            ans[mp[s[cnt].pos]]=(v[i][j].pos-s[cnt].pos)/2;
                            ans[mp[v[i][j].pos]]=(v[i][j].pos-s[cnt].pos)/2;
                            cnt--;
                        }
                    }
                }
                // for(int i=1;i<=n;i++){
                //     printf("%d ",ans[i]);
                // }
                // cout<<endl;
                node lastl={0,0};
                for(int j=0;j<v[i].size();j++){
                    if(v[i][j].dir==1&&ans[mp[v[i][j].pos]]==-1){
                        if(lastl.pos==0)lastl=v[i][j];
                        else{
                            //cout<<lastl.pos<<" "<<v[i][j].pos<<endl;
                            ans[mp[lastl.pos]]=lastl.pos+(v[i][j].pos-lastl.pos)/2;
                            ans[mp[v[i][j].pos]]=lastl.pos+(v[i][j].pos-lastl.pos)/2;
                            lastl=(node){0,0};
                        }
                    }
                }
                // for(int i=1;i<=n;i++){
                //     printf("%d ",ans[i]);
                // }
                // cout<<endl;
                node lastr={0,0};
                for(int j=v[i].size()-1;j>=0;j--){
                    if(v[i][j].dir==0&&ans[mp[v[i][j].pos]]==-1){
                        if(lastr.pos==0)lastr=v[i][j];
                        else{
                            //cout<<lastl.pos<<" "<<v[i][j].pos<<endl;
                            ans[mp[lastr.pos]]=m-lastr.pos+(lastr.pos-v[i][j].pos)/2;
                            ans[mp[v[i][j].pos]]=m-lastr.pos+(lastr.pos-v[i][j].pos)/2;
                            lastr=(node){0,0};
                        }
                    }
                }
                // for(int i=1;i<=n;i++){
                //     printf("%d ",ans[i]);
                // }
                // cout<<endl;
                if(lastl.pos!=0&&lastr.pos!=0){
                    ans[mp[lastl.pos]]=((m-lastr.pos)+lastl.pos+m)/2;
                    ans[mp[lastr.pos]]=((m-lastr.pos)+lastl.pos+m)/2;
                }
            }
            for(int i=1;i<=n;i++){
                printf("%d ",ans[i]);
            }
            cout<<endl;
        }
    }
    

    D-Armchairs

    题意:
    (n)把椅子,至多有(n/2)个人坐在椅子上,问让所有有人坐的椅子都变空的最小代价是多少,坐在第(i)把椅子上的人移动到第(j)把椅子上的代价为 (abs(i-j))

    思路:

    • 考虑(dp)(dp[i][j])表示让前(i)把椅子的人移动到前(j)把空椅子上的人的最小代价。
    • (dp)数组初始为(inf),可以推出转移方程 (dp[i+1][j]=min(dp[i][j],dp[i][j-1]+abs(pos[i]-pos[j-1])))

    代码:

    #include<bits/stdc++.h>
    #define ll long long
    #define MOD 998244353 
    #define INF 0x3f3f3f3f
    #define mem(a,x) memset(a,x,sizeof(a))  
    #define ios ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
    using namespace std;
    
    vector<int>a,b;
    int dp[5005][5005];  //表示前i个移动到j个空位置的最小花费
    int main()
    {
    	int n;
    	scanf("%d",&n);
    	for(int i=1;i<=n;i++){
    		int num;
    		scanf("%d",&num);
    		if(num==0)a.push_back(i);
    		else b.push_back(i);
    	}
    	memset(dp,0x3f3f,sizeof dp);
    	dp[0][0]=0;
    	for(int i=0;i<a.size();i++){
    		dp[i+1][0]=0;
    		for(int j=1;j<=b.size();j++){
    			int x=b[j-1];
    			int y=a[i];
    			dp[i+1][j]=min(dp[i][j],dp[i][j-1]+abs(x-y));
    		}
    	}
    	cout<<dp[a.size()][b.size()]<<endl;
    	return 0;
    }
    
    越自律,越自由
  • 相关阅读:
    九度oj 题目1051:数字阶梯求和
    九度oj 题目1472:求两个多项式的和
    九度oj 题目1173:查找
    九度oj 题目1447:最短路
    九度oj 题目1104:整除问题
    [Luogu] 维护序列
    [Luogu] 计算系数
    [Luogu] 聪明的质监员
    [Luogu] Mayan游戏
    [Luogu] 选择客栈
  • 原文地址:https://www.cnblogs.com/ha-chuochuo/p/14778258.html
Copyright © 2020-2023  润新知