当前位置:首页 » 《随便一记》 » 正文

2023华为软件精英挑战赛赛题解析及baseline(C++实现)

25 人参与  2023年03月31日 11:54  分类 : 《随便一记》  评论

点击全文阅读


一年一度的华为软件精英挑战赛又开始了,今年的题目感觉比以往更难些。因为不仅把数据都给你了,连判题器都给你了。

任务介绍

题目描述大概内容如下:

在一张50m*50m的地图上,分布着许多固定的工作台和可以移动的机器人(4个)。可以把这些工作台看作一个又一个的点,他们可以生产、消耗某种产品。机器人只能通过前进,后退,旋转等操作进行移动,当移动到工作台后,可以购买产品、出售产品,此外在携带产品时可以随时销毁产品。

开始时,你有一笔钱(20万),通过调度机器人在各个工作台之间进行购买、出售产品,从而赚取差价获利。比如,你可以让机器人移动到某个工作台a购买产品1(假设花费100元),然后移动到另一个工作台b出售产品1(假设售价1000元),那么你可以赚取900元的差价。

题目给定的机器人数量为4,工作台数量小于50,也就是说这需要你调度4个机器人在不超过50个的工作台之间通过买卖产品赚取差价,在三分钟内获得最大利润。

输入输出
在这里插入图片描述
个人觉得,任何程序怎么写,搞明白输入输出最关键。下面我简单就官方提供的代码对输入输出做一个简单的分析。

```cpp#include <iostream>using namespace std;bool readUntilOK() {    char line[1024];    while (fgets(line, sizeof line, stdin)) {        if (line[0] == 'O' && line[1] == 'K') {            return true;        }        //do something    }    return false;}int main() {    //1.判题器输入//第一个readUntilOK,判题器输入地图数据,我们可以在这个函数里面进行一个地图的初始化,比如把地图保存在一个二维数组中等。    readUntilOK();    //选手程序输出一个OK,相当于告诉判题器map数据初始化完成,可以发帧了    puts("OK");    fflush(stdout);    int frameID;    //不断地读取数据,直到EOF    while (scanf("%d", &frameID) != EOF) {        //第二个readUntilOK,我们可以在这个函数里处理每一帧的数据,具体的讲,我们可以把每帧画面下,工作台的状态及机器人的状态进行更新保存。        readUntilOK();                //2.我们的输出        //首先输出帧号,用于判题器判断是否跳帧(就是序号是否连续)        printf("%d\n", frameID);        int lineSpeed = 3;        double angleSpeed = 1.5;        //然后输出你对机器人的指令,包括前进、旋转、购买、出售等等。        for(int robotId = 0; robotId < 4; robotId++){            printf("forward %d %d\n", robotId, lineSpeed);            printf("rotate %d %f\n", robotId, angleSpeed);        }        printf("OK\n", frameID);        fflush(stdout);    }    return 0;}

解决思路

如何让机器人移动到工作台。

这涉及到机器人导航的问题,具体可以参考这位知乎作者的文章https://zhuanlan.zhihu.com/p/612863940。

如何避免碰撞

采取何种策略规划机器人的路径

比如让每个机器人设置一条固定的线路,让各个机器人分工协作。
更新一个简单的思路:
可以让四个机器人,每个机器人负责某种物品的购买和出售。比如:让0号机器人负责原料1的购买和出售,让1号机器人负责原料2的购买和出售,让2号机器人负责材料3的购买和出售(1,2,3号物品原材料生成出来地速度快,所以用三个机器人负责每种物品地买卖),让3号机器人负责物品4,5,6的购买和出售。这样形成一条流水线,让物品不断地加工出来,再出售出去。
更新一个思路:
按买卖物品任务按优先级分发给每个机器人执行,具体来说,我们可以把每个需要材料加工成产品的过程看作一个任务,比如4号工作台,它需要机器人运送材料1和材料2,那么把材料1和材料2运送到4号工作台就可以看作一个任务,所以我们就可以把每个需要材料加工的工作台看作一个任务点,给其分配一个优先级(你可以根据该工作台距离生成材料1和材料2的工作台的距离去定,距离越远优先级越低等等,这里涉及你采用什么样的策略去定优先级,应该很关键)。把任务放入任务队列,把优先级高的分配给当前闲置机器人去执行。

Baseline

自己花了一两天写出了一个baseline,我的baseline实现的功能就是移动一个机器人到某一个工作台购买产品,然后移动到另一个工作台出售产品。首先我根据机器人坐标和工作台坐标,求出了机器人朝向(航向)与目标工作台的夹角

在这里插入图片描述
然后设置一个初始线速度forward和旋转速度rotate,不断地减少夹角,当夹角小于一定程度,增大forward,rotate变为0,快速向工作台移动。用这样地方式在两个工作台之间往来购买和出售商品。

提交后的得分:
在这里插入图片描述
我这只是实现了一个baseline,虽然分数比较低,但是我实现了机器人移动到目标工作台的功能,并且我只移动了一个机器人,使其在两个工作台之间移动一次就停止了,所以还有很大的提升空间。由于本人也忙于毕业大论文,没有太多时间继续优化,可能后面也不会继续搞了,需要的话可以在我的资源下载。
图形化界面展示效果如下:

QQ录屏20230318100930


如何线下查看每张地图分数(window下):
首先你要把你代码(c++)生成的exe文件找到,放到判题器所在目录下:
我放在Demo\my目录下,我代码生成的exe文件也叫SimpleDemo.exe
然后在判题器所在目录下打开命令行窗口(ctrl + 鼠标右键)输入

 .\robot.exe Demo\my\SimpleDemo.exe -f -m maps\1.txt

改变后面的txt文件就能看不同地图下程序的得分。
演示视频如下:

判分


点击全文阅读


本文链接:http://zhangshiyu.com/post/57539.html

<< 上一篇 下一篇 >>

  • 评论(0)
  • 赞助本站

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

关于我们 | 我要投稿 | 免责申明

Copyright © 2020-2022 ZhangShiYu.com Rights Reserved.豫ICP备2022013469号-1