一年一度的华为软件精英挑战赛又开始了,今年的题目感觉比以往更难些。因为不仅把数据都给你了,连判题器都给你了。
任务介绍
题目描述大概内容如下:
在一张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文件就能看不同地图下程序的得分。
演示视频如下:
判分