这道题使我第一次体会到了代码十分钟,dbug一小时。。。
马拉松接力赛
题目描述
某城市冬季举办环城25km马拉松接力赛,每个代表队有5人参加比赛,比赛要求每个的每名参赛选手只能跑一次,一次至少跑1km、最多只能跑10km,而且每个选手所跑的公里数必须为整数,即接力的地方在整公里处。
刘老师作为学校代表队的教练,精心选择了5名长跑能手,进行了训练和测试,得到了这5名选手尽力连续跑1km、2km、…、10km的所用时间。现在他要进行一个合理的安排,让每个选手跑合适的公里数,使学校代表队跑完25km所用的时间最短。根据队员的情况,这个最短的时间是惟一的,但安排方案可能并不惟一。
根据测试情况及一般运动员的情况得知,连续跑1km要比连续跑2km速度快,连续跑2km又要比连续跑3km速度快……也就是说连续跑的路程越长,速度越慢,当然也有特殊的,就是速度不会变慢,但是绝不可能变快。
输入输出格式
输入格式:5行数据,分别是1到5号队员的测试数据,每行的10个整数,表示某一个运动员尽力连续跑1km、2km、…、10km所用的时间。
输出格式:两行,第一行是最短的时间,第二行是五个数据,分别是1到5号队员各自连续跑的公里数。
输入输出样例
对于这道题,如果使用暴力的全排列来做的话,那么显然时间复杂度会妥妥的达到10^5,如果我们想要过掉所有的数据点的话,暴力排列就显得十分无力,所以我们要选择别的方法。
这道题的特点在于要求最小值,因此我们可以往贪心和dp上去想,这里介绍一种贪心算法:
由于每个人都需要跑,因此第一步肯定要将每一个人分配一公里,那么接下来该怎么办呢?
显然无论在什么状态下,我们都要找跑这一公里最快的人来跑,因此我们只要每一次找每个人跑下一公里所需的时间再进行比较,就可以找到所需时间最短的人,将其标记即可。
或许你会问:每个人只能上场一次,如果按照刚刚的思路不就使得每个人上场多次了吗?
其实这并不是问题,由于我们要找的是最短的时间,因此无论先跑还是后跑,最优方案的总时长不变,所以不会对结果造成影响。
关于无后效性,由于每一步只受之前的状态影响,所以显然没有后效性。
最后有一个注意事项:开的标记数组不能超过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 %d %d %d %d %d",ans,c[1],c[2],c[3],c[4],c[5]); return 0; }