马拉松接力赛

这道题使我第一次体会到了代码十分钟,dbug一小时。。。

马拉松接力赛

题目描述

某城市冬季举办环城25km马拉松接力赛,每个代表队有5人参加比赛,比赛要求每个的每名参赛选手只能跑一次,一次至少跑1km、最多只能跑10km,而且每个选手所跑的公里数必须为整数,即接力的地方在整公里处。

刘老师作为学校代表队的教练,精心选择了5名长跑能手,进行了训练和测试,得到了这5名选手尽力连续跑1km、2km、…、10km的所用时间。现在他要进行一个合理的安排,让每个选手跑合适的公里数,使学校代表队跑完25km所用的时间最短。根据队员的情况,这个最短的时间是惟一的,但安排方案可能并不惟一。

根据测试情况及一般运动员的情况得知,连续跑1km要比连续跑2km速度快,连续跑2km又要比连续跑3km速度快……也就是说连续跑的路程越长,速度越慢,当然也有特殊的,就是速度不会变慢,但是绝不可能变快。

输入输出格式

输入格式:

5行数据,分别是1到5号队员的测试数据,每行的10个整数,表示某一个运动员尽力连续跑1km、2km、…、10km所用的时间。

输出格式:

两行,第一行是最短的时间,第二行是五个数据,分别是1到5号队员各自连续跑的公里数。

输入输出样例

输入样例#1:  复制
333 700 1200 1710 2240 2770 3345 3956 4778 5899 
300 610 960 1370 1800 2712 3734 4834 5998 7682
298 612 990 1540 2109 2896 3790 4747 5996 7654
289 577 890 1381 1976 2734 3876 5378 6890 9876
312 633 995 1407 1845 2634 3636 4812 5999 8123
输出样例#1:  复制
9905
6 5 5 4 5

对于这道题,如果使用暴力的全排列来做的话,那么显然时间复杂度会妥妥的达到10^5,如果我们想要过掉所有的数据点的话,暴力排列就显得十分无力,所以我们要选择别的方法。

这道题的特点在于要求最小值,因此我们可以往贪心和dp上去想,这里介绍一种贪心算法:

由于每个人都需要跑,因此第一步肯定要将每一个人分配一公里,那么接下来该怎么办呢?

显然无论在什么状态下,我们都要找跑这一公里最快的人来跑,因此我们只要每一次找每个人跑下一公里所需的时间再进行比较,就可以找到所需时间最短的人,将其标记即可。

扫描二维码关注公众号,回复: 4582493 查看本文章

或许你会问:每个人只能上场一次,如果按照刚刚的思路不就使得每个人上场多次了吗?

其实这并不是问题,由于我们要找的是最短的时间,因此无论先跑还是后跑,最优方案的总时长不变,所以不会对结果造成影响。

关于无后效性,由于每一步只受之前的状态影响,所以显然没有后效性。

最后有一个注意事项:开的标记数组不能超过10,否则会导致二维数组越界。

最后,附上本题代码。

#include<cstdio>
using namespace std;
int a[6][11],aa[6][11],c[6],ans;
int main()
{
    c[1]=1;c[2]=1;c[3]=1;c[4]=1;c[5]=1;
    for(int i=1;i<=5;i++)
    {
        for(int j=1;j<=10;j++)
        {
            scanf("%d",&a[i][j]);
            aa[i][j]=a[i][j]-a[i][j-1];
        }
    }
    for(int i=1;i<=20;i++)
    {
        int min=2147483647,temp=0;
        for(int j=1;j<=5;j++)
        {
            if(aa[j][c[j]+1]<min&&c[j]+1<=10)
            {
                min=aa[j][c[j]+1];
                temp=j;
            }
        }
        c[temp]++;
    }
    for(int i=1;i<=5;i++)
    {
        ans+=a[i][c[i]];
    }
    printf("%d\n%d %d %d %d %d",ans,c[1],c[2],c[3],c[4],c[5]);
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/yufenglin/p/10152133.html