算法学习系列(贪心算法)—机器人攀登问题

问题描述:
要举办一场机器人攀登接力赛,规定攀登总高度为m米,每队参赛机器人个数为n(2≤n≤10),每个机器人只能攀登1次,至少攀登1米,至多攀登k(1≤k≤20)米,并且只能在整米处接力。某队有n个机器人,在平时训练时进行了性能测试,得出每个机器人连续攀登1米、2米、…、k米的时间,机器人攀登路程越长,攀登速度就越慢。设计一个贪心算法,安排该队各机器人的攀登高度,使总攀登时间最少。

输入数据:
第一行,3个整数,由空格分隔,分别是参赛机器人数n、每个机器人允许攀登的最大高度k和总攀登高度m;
第二行开始的n行,每行k个整数,用空格分隔,分别表示机器人连续攀登1米、2米、…、k米的时间。

输出数据
第一行,为各机器人安排的攀登高度,用空格分隔;
第二行,总的最少攀登时间。

算法思想:
算法使用贪心的思想,因为每个机器人都必须要用到,因从先给每个机器人爬1米,随后使用贪心策略,每次选取这四个机器人向上爬
一米要增加的最小时间所对应的机器人进行向上爬一米,得到的最后每个机器人的米数即为最短时间的攀爬策略

算法步骤:
1、用一个time整型记录目前已花费的时间 ,一个height整型记录目前的高度,一个now_height数组记录每个机器人目前所在的高度,先让每个机器人上爬一米,每个机器人
now_height++,time += robot_height[i][0]
2、随后对每个机器人上爬一米的时间robot_height[i][now_height[i]]-robot_height[i][now_height[i] - 1]进行比较,选出最短的时间
对该机器人的now_height++ 直到height大于total_height为止
3、最后得到的now_height数组即为各个机器人的贪心策略得出的最短时间的攀爬策略

头文件代码:
定义了一个类、声明了用到的各个成员变量,公有的climb函数是调用贪心算法的入口
RobotClimbing.h:

#ifndef ROBOTCLIMBING_H_INCLUDED
#define ROBOTCLIMBING_H_INCLUDED

#include<iostream>
#include<fstream>
#include<malloc.h>

using namespace std;

class RobotClimbing
{
    int num;    //表示机器人的总数,从文件中读取
    int most_height;    //每个机器人最多可以爬的高度,从文件中读取
    int total_height;   //目标高度,从文件中读取
    int **robot_height;     //一个二维数组,用于记录各个机器人爬到不同高度所需要的时间
    int time;       //记录目前已花费的时间
    int height;     //记录目前已爬上的高度
    int *now_height;    //用于记录各个机器人目前已经爬到的高度
    ofstream fout;

    void readFile(char *in);
public:
    RobotClimbing(char *in ,char *out);
    ~RobotClimbing()
    {
        if(robot_height)
        {
            free(robot_height);
        }
        if(now_height)
        {
            free(now_height);
        }
    }
    void climb();
};
#endif // ROBOTCLIMBING_H_INCLUDED

cpp文件:
程序中所有的数据都从文件中读取、大家调用的时候请自己在同一目录下建立input.txt,其中输入数据为:

5 10 25
24 49 75 102 130 160 192 230 270 320
23 48 75 103 139 181 224 274 344 415
22 49 80 180 280 380 480 580 680 780
25 51 80 120 170 220 270 320 370 420
23 49 79 118 158 200 250 300 350 400

RobotClimbing.cpp:

#include "RobotClimbing.h"

void RobotClimbing::readFile(char *in)
{
    ifstream fin(in);
    fin>>num>>most_height>>total_height;        //从文件中读取机器人数量,每个机器人最高的高度,以及目标高度

    robot_height = (int **)malloc(sizeof(int *)*num);

    now_height = (int *)malloc(sizeof(int) * num);


    for(int i = 0 ;i<num ;i++)
    {
        robot_height[i] = (int *)malloc(sizeof(int ) * most_height);
    }

    for(int i = 0 ;i<num ;i++)
    {
        for(int j = 0 ;j<most_height ;j++)
        {
            fin>>robot_height[i][j];
        }
    }
    fin.close();
}

RobotClimbing::RobotClimbing(char *in ,char *out):fout(out)
{
    readFile(in);
}

void RobotClimbing::climb()
{
    height = num;
    time = 0;

    for(int i = 0 ;i<num ;i++)
    {
        time += robot_height[i][0];
        now_height[i] = 1;
    }

    while(height < total_height)
    {
        int min = 1000;    //记录各个机器人当前再增加一米需要增加的最小的时间
        int rec;            //记录达到最小时间的机器人的序号
        for(int i = 0 ;i<num ;i++)  //找到在增加一米,所需增加的时间最小的机器人
        {
            if(robot_height[i][now_height[i]]-robot_height[i][now_height[i] - 1] < min && now_height[i] < most_height)
            {               //if语句判断该机器人增加的时间是否比已记录的最小时间小,并且该机器人爬的距离不能超过最高距离

                min = robot_height[i][now_height[i]]-robot_height[i][now_height[i] - 1];
                rec = i;    //记录下第i个机器人有最小的时间
            }
        }
        height++;   //增加一米
        time += robot_height[rec][now_height[rec]]-robot_height[rec][now_height[rec] - 1];  //加上当前高度记录的机器人增加一米所需要的最小时间
        now_height[rec]++;  //该机器人的高度增加一米
    }
    for(int i = 0;i<num ;i++ )
    {
        fout<<now_height[i]<<' ';   //将最后的结果输出到文件
    }
    fout<<endl<<time;
}

最后是主函数的调用入口

#include "RobotClimbing.h"

using namespace std;

int main()
{
    char *in = "input.txt";
    char *out = "output.txt";
    RobotClimbing robotclimb(in ,out);
    robotclimb.climb();
}

输出到文件中的最后结果为:
9 5 3 4 4
727

  • 2
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值