P1252 马拉松接力赛 (洛谷)

题目描述

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

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

根据测试情况及一般运动员的情况得知,连续跑 1k 要比连续跑 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*10,所以很容易往贪心或者dp上面去想。由于dp还没想出来,就先考虑贪心的做法。

        首先,我们把每个人跑每个1km所要用的时间,由于每个人都是需要跑的,所以每个人起步距离1km。这个时候就要开始贪了,怎么贪?

        我们只需要让每个1km跑的最快的来跑这个1km即可

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

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

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

#include<iostream>
#include<cmath>
#include<cstring>
#include<cstdio>
#include<stack>
#include<string>
#include<algorithm>
#include<unordered_map>
#include<map>
#include<bitset>
#include<cstring>
#include <unordered_set>
//#include<priority_queue>
#include<queue>
#include<deque>
#include<set>
#include<stdlib.h>
#define dbug cout<<"hear!"<<endl;
#define rep(a,b,c) for(ll a=b;a<=c;a++)
#define per(a,b,c) for(ll a=b;a>=c;a--)
#define no cout<<"NO"<<endl;
#define yes cout<<"YES"<<endl;
#define endl "\n"
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
//priority_queue<int,vector<int>,greater<int> >q;
using namespace std;
typedef long long ll;
typedef long double ld;
typedef pair<ll, ll> PII;
typedef pair<long double,long double> PDD;
 ll  INF = 0x3f3f3f3f;
//const ll LINF=LLONG_MAX;
// int get_len(int x1,int y1,int x2,int y2)
// {
//   return (x2-x1)*(x2-x1) + (y2-y1)*(y2-y1);
// }
const ll N = 1e6+ 10;
const ll mod1 =998244353;
const ll mod2 =1e9+7;
const ll hash_num = 3e9+9;
ll n,m,ca, k,ans;
ll arr[N],brr[N],crr[N],drr[N];
//ll h[N],ne[N],e[N],w[N],book[N],idx;
//ll idx;

// void add(ll a, ll b , ll c)
// {
//   e[idx] = b, w[idx] = c,ne[idx] = h[a], h[a] =idx ++ ; 
// }

int a[15][15];
int b[15][15];
int c[10];
void solve()
{
  rep(i,1,5)
  {
    c[i]=1;
  }
  rep(i,1,5)
  {
    rep(j,1,10)
    {
      cin >> a[i][j];
      b[i][j]=a[i][j]-a[i][j-1];
    }
  }
 rep(i,1,20)
 {
  ll minx=INF;
  ll f=0;
  rep(j,1,5)
  {
    if(b[j][c[j]+1]<minx && c[j]+1<=10)
    {
      f=j;
      minx=b[j][c[j]+1];
    }
  }
  c[f]++;
 }
 ll ans=0;
 rep(i,1,5)
 {
  ans+=a[i][c[i]];
 }
 cout << ans << endl;
 rep(i,1,5)
 {
  cout << c[i]<<' ';
 }
}


int main()
{
   IOS;
   ll _;
    _=1;
    //scanf("%lld",&_);
    //cin>>_;

    ca=1;
    while(_--)
    {
      solve(); 
      ca++;
    }    
    return 0;
}


 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值