Codeforces Round #753 (Div. 3) a-d

本文详细解析了五道算法竞赛题目,包括线性键盘的代价计算、奇数草蜢的跳跃路径、数组元素提取的最小值、蓝色红色排列组合以及机器人在棋盘上的移动。通过暴力模拟、寻找规律、排序分析和贪心策略,逐一解答这些问题,展示了动态规划和贪心算法在解决复杂问题时的有效性。
摘要由CSDN通过智能技术生成

A. Linear Keyboard

题目

题意
先给定26个字母的排列顺序 再给一个字符串s 字符串s的代价为s中相邻两个字母在26个字母排列顺序的距离 求s的代价总和

思路
暴力模拟

代码

#include<cstdio>
#include<cstring>//memset
#include<iostream>//c++
#include<algorithm>//stl
#include<string>
#define N 400005
#define mod 1000000007
using namespace std;
typedef long long ll;

ll t,n,k,te,a[30];

string s,st;

int main()
{
    ios::sync_with_stdio(false);
    cin>>t;
    while(t--)
    {
        ll ans=0;
        cin>>st>>s;
        for(int i=0;i<st.size();i++)
        {
            a[st[i]-'a']=i;
        }
        for(int i=1;i<s.size();i++)
        {
            ans+=abs(a[s[i]-'a']-a[s[i-1]-'a']);
        }
        cout<<ans<<endl;

    }
    return 0;
}

B. Odd Grasshopper

题目

题意
跳跃步长开始为1 然后每次不断增加1(步长依次为1,2,3…)
如果当前点是偶数 就向左跳 如果当前点是奇数 就向右跳
现在给出起始点x 和跳跃的次数n 问n次跳跃后会在哪个点

思路
打表找出规律 每第4个数都会变成x 第2个数会根据开始位置的奇偶变成 x-1或者x+1 其它两位数字在根据奇偶定下初始位置后 给据每经过4个数 就变化4的规律

代码

#include<cstdio>
#include<cstring>//memset
#include<iostream>//c++
#include<algorithm>//stl
#include<string>
#define N 400005
#define mod 1000000007
using namespace std;
typedef long long ll;

ll t,x,n,k;


int main()
{
    ios::sync_with_stdio(false);
    cin>>t;
    while(t--)
    {
        cin>>x>>n;
        /*ll t=x;
        for(int i=1;i<=n;i++)
        {
            if(t%2==0)
                t-=i;
            else
                t+=i;
            cout<<t<<": "<<i<<endl;
        }
        cout<<endl;*/
        //打表
        ll cnt=n/4,te=n%4;
        if(te==0)
            cout<<x<<endl;
        else if(te==2)
        {
            if(x%2)
            {
                cout<<x-1<<endl;
            }
            else
                cout<<x+1<<endl;
        }
        else if(te==1)
        {
            if(x%2)
                cout<<(x+1)+4*cnt<<endl;
            else
                cout<<(x-1)-4*cnt<<endl;
        }
        else
        {
            if(x%2)
                cout<<x-4*(cnt+1)<<endl;
            else
                cout<<x+4*(cnt+1)<<endl;
        }

    }
    return 0;
}

C. Minimum Extraction

题目

题意
给一个数组 每次找到最小的一个数 然后其余数-最小数 然后删除这个最小数 问这样操作找到数组的最小值最大是多少

思路
下一次的最小值是这一次次最小值与最小值之差 问题转变成排序后 不断找相邻的差值 就能得出最小值的所有可能 找最大值

代码

#include<cstdio>
#include<cstring>//memset
#include<iostream>//c++
#include<algorithm>//stl
#define N 400005
#define mod 1000000007
using namespace std;
typedef long long ll;

ll t,x,n,k,a[N],te,ans;

int main()
{
    ios::sync_with_stdio(false);
    cin>>t;
    while(t--)
    {
        cin>>n;
        for(int i=0;i<n;i++)
            cin>>a[i];
        sort(a,a+n);
        ll ans=a[0];
        for(int i=1;i<n;i++)
        {
            ans=max(ans,a[i]-a[i-1]);
        }
        cout<<ans<<endl;
    }
    return 0;
}

D. Blue-Red Permutation

题目

题意
给一个长度为n的数组a 数组的每位有一个颜色 蓝色表示这个数可以不断减1 红色表示这个数可以不断加1 问这个数组最后是否能变成包含1-n所有数字的数组(顺序可以乱 每个数出现一次)

思路
贪心的想法去向 能组成符合的数组 最低要求是蓝色组成1到蓝色个数的数 红色组成后面大的数 达成这个要求的就行

代码

#include<cstdio>
#include<cstring>//memset
#include<iostream>//c++
#include<algorithm>//stl
#include<string>
#include<set>
#include<queue>
#include<stack>
#define N 400005
#define mod 1000000007
using namespace std;
typedef long long ll;

ll t,x,n,k,a[N],te,ans;
string s;
vector<ll> vr,vb;
bool cmp(ll aa,ll bb)
{
    return aa>bb;
}

int main()
{
    ios::sync_with_stdio(false);
    cin>>t;
    while(t--)
    {
        vr.clear();
        vb.clear();
        cin>>n;
        for(int i=0; i<n; i++)
            cin>>a[i];
        cin>>s;
        for(int i=0; i<s.size(); i++)
        {
            if(s[i]=='B')
                vb.push_back(a[i]);
            else
                vr.push_back(a[i]);
        }
        sort(vr.begin(),vr.end(),cmp);
        sort(vb.begin(),vb.end());
        int flag=1;
        for(int i=0; i<vb.size(); i++)
        {
            if(vb[i]<i+1)
            {
                flag=0;
                break;
            }
        }
        if(flag==0)
            cout<<"NO\n";
        else
        {
            for(int i=0; i<vr.size(); i++)
            {
                if(vr[i]>n-i)
                {
                    flag=0;
                    break;
                }
            }
            if(flag)
                cout<<"YES\n";
            else
                cout<<"NO\n";
        }
    }
    return 0;
}

E. Robot on the Board 1

题目

题意
给定n行m列的方格 再给定可以含上下左右走指令的字符串 问起点定在哪 才能执行更多的移动指令且不超过方格

思路
分为横向和竖向的两个方向不断记录执行每个指令后的上下左右四个方向的历史最值 当某个方向的跨越长度超过方格大小就表示无法执行后面的指令了

代码

#include<cstdio>
#include<cstring>//memset
#include<iostream>//c++
#include<algorithm>//stl
#include<string>
#include<set>
#include<queue>
#include<stack>
#include<vector>
#define N 400005
#define mod 1000000007
using namespace std;
typedef long long ll;

ll t,x,n,m;
string s;


int main()
{
    ios::sync_with_stdio(false);
    cin>>t;
    while(t--)
    {
        cin>>n>>m;
        cin>>s;
        int maxx=0,minx=0,maxy=0,miny=0;
        int dx=0,dy=0;
        int ansx=1,ansy=1;
        for(int i=0;i<s.size();i++)
        {
            if(s[i]=='R')
            {
                dx++;
                maxx=max(dx,maxx);
            }
            else if(s[i]=='L')
            {
                dx--;
                minx=min(dx,minx);
            }
            else if(s[i]=='U')
            {
                dy++;
                maxy=max(dy,maxy);
            }
            else
            {
                dy--;
                miny=min(dy,miny);
            }
            if(maxx-minx+1>m||maxy-miny+1>n)
                break;
            ansx=maxy+1;
            ansy=1-minx;

        }
        cout<<ansx<<" "<<ansy<<endl;
    }
    return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值