算法作业五 贪心算法

题目2:有n个人参加一个马拉松接力游戏,游戏规定每个人可以根据自己的情况随时终止游戏并由下一个人继续接力。由于每个人的情况不同,即使同一个人也不可能在整个游戏过程中永远保持很好的状态。因此要求他们在比赛前根据每个人的情况需要制定一个接力规则,使整个比赛的时间越少越好。请编写程序帮助他们制定这样的接力方案。

输入要求:输入的第1行有三个整数n,k和m,分别表示参加接力的人的个数,每个人最多可以跑的公里数以及接力赛的距离(以公里为单位)。其后的n行,每行有k个整数,分别表示每个人跑整数1公里,2公里,….,K公里所花费的时间(以秒为单位,整数)。游戏要求每个人都必须参加比赛,且每次只能跑到整数公里后才能换人。

输出要求:输出1个整数,表示这些人跑完整个接力赛最少要花多少时间。

样例输入:

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

样例输出:

727

大概思路如下

        该问题求解接力赛所用的最短时间,因为每个人必须参加并且只能跑一次,所以每个人必须不间断跑n公里,最后总和为25公里。因为每个人的时间都是随着里程数的增多而增多的,所以可以将25公里分为25*1公里,每次分配只要找一公里时间最快的就可以。因此可以根据输入求得一个单位公里的时间数组,每次搜寻只要找该列最快的即可。因此可以设置一个Sub[i][j]的二维数组,存储每个人单位时间内花费的时间,如下所示:

        24    25    26    27    28    30    32    38    40    50

        23    25    27    28    36    42    43    50    70    71

        22    27    31    100    100    100    100    100    100    100

        25    26    29    40    50    50    50    50    50    50

        23    26    30    39    40    42    50    50    50    50

因为对同一个人来说,第j列花费的时间一定是<=第j+1列的,但对于不同的人,花费的时间有差异,因此在搜索时,设置Min为最小值,根据Sub[i][j]的值及时更新Min的值。当总公里数=m时结束搜索。

二 程序代码

#include<iostream>

using namespace std;

#define Maxsize 999

int grade[Maxsize][Maxsize] ;//存放每个人的成绩

int Sub[Maxsize][Maxsize];//分块之后每个人1公里的时间

int Min;//比较数

int m, n, k;//总里程数,人数,最大公里数,

int sum = 0;//总时长

int km = 0;//里程数

//可以把25公里分割成25块,每次找一公里中跑的最快的那个

void Search()

{

    for (int i = 1;i <= n;i++)

    {

         for (int j = 1;j <= k;j++)

         {

             Sub[i][j] = grade[i][j] - grade[i][j - 1];

         }

    }

}

void Calculate(int a)

{

    int i = 1;

    int j = 1;

    int Min = Maxsize;

    //每公里遇到需要派人时,首先挑选时间最短的

    while (km <m)

    {

         if (i % (n+1) == 0)//按Sub数组的列进行搜索

         {

             i = 1;

             j++;

         }else

         {

             if (Sub[i][j] <= Min)//选中该人

             {

                  Min = Sub[i][j];

                  sum += Sub[i][j];

                  i++;//进行下一次选择

                  km++;

             }

             if (Sub[i][j] > Min) //当前比最小的大

             {

                  if (Sub[i][j] < Sub[i][j + 1] && Sub[i][j]<=a)

                  {

                      Min = Sub[i][j];//存储较大的元素,方便后续比较

                      sum += Sub[i][j];

                      km++;

                      i++;

                  }

                  else i++;

             }

         }

    }

}

int  main()

{

    memset(grade, 0, sizeof(grade));

    memset(Sub, 0, sizeof(Sub));

    cin >> n >> k >> m;

    for (int i = 1;i <= n;i++)

    {

         for (int j = 1;j <= k;j++)

         {

             cin >> grade[i][j];

         }

    }

    Search();

    int a = Sub[1][k - 1];//单位公里内允许花费的最大时间

    Calculate(a);

    cout << sum;

    return 0;

}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值