您的位置:首页 > 其它

ACM: 华东师范oj 1600&n…

2016-05-19 23:26 375 查看
公路巡逻

Description

在一条没有分岔的高速公路上有n个关口,相邻两个关口之间的距离都是10km。所有车辆在这条高速公路上的最低速度为60km/h,最高速度为120km/h,并且只能在关口处改变速度。

巡逻的方式是在某个时刻Ti从第ni个关口派出一辆巡逻车匀速驶抵第(ni+1)个关口,路上耗费的时间为ti秒。

两辆车相遇是指它们之间发生超车或者两车同时到达某关口(同时出发不算相遇)。

巡逻部门想知道一辆于6点整从第1个关口出发去第n个关口的车(称为目标车)最少会与多少辆巡逻车相遇,请编程计算之。假设所有车辆到达关口的时刻都是整秒。

Input

输入第一行为两个用空格隔开的整数,分别为关口数n和巡逻车数m。(1<=ni<=Ti<=23:00:00,300<=ti<=600)
Output

输出文件第一行为目标车与巡逻车相遇次数。第二行为目标车与巡逻车相遇次数最少时最早到达第n个关口的时刻(格式同输入中的Ti)。
Sample
Input


3 2

1 060000 301

2 060300 600

Sample
Output


0

061301

题意: 你的车从6点整开始出发, 从1关口到n关口,
每次改变速度只可以在关口处(60km/h<=v<=120km/h),

     
每个关口相距10km, 现在又m辆巡逻车, 给出每部巡逻车从ni关口出发的时间和到达下个关口的时间,

      现在要你求出在最少相遇次数下,
最早到达n关口的时间和相遇次数.
 
解题思路:

     
1. 设dp[i][j]: 到达第i个关口时, 花费的时间为j与巡逻车相遇的最少次数.

        
设time[j][j+k]: 时间j到j+k内相遇的次数.

        
方程: dp[i+1][j+k] = min(dp[i+1][j+k], dp[i][j]+time[j][j+k]);

        
结果: min(dp
[i]);
 
代码:
#include
<cstdio>

#include <iostream>

#include <cstring>

using namespace std;

#define MAX 305

#define MAXSIZE 52

const int INF = (1<<29);
struct node

{

 int start, end;

}car[MAX][MAX];
int n, m;

int dp[MAXSIZE][MAXSIZE*600];

int num[MAX];
inline int change(int time)

{

 int hour = time/10000;

 int min = (time/100)0;

 int second = time0;

 return ((hour-6)*60+min)*60+second;

}
inline int changeBack(int time)

{

 int second = time`;

 time /= 60;

 int min = time`;

 time /= 60;

 int hour = time+6;

 return (hour*10000)+min*100+second;

}
inline int min(int a, int b)

{

 return a < b ? a : b;

}
void DP()

{

 int i, j, k;

 dp[0][0] = 0;

 n--;

 for(i = 0; i < n; ++i)

 {

  for(j = i*300; j
<= i*600; ++j)

  {

   for(k = 300;
k <= 600; ++k)

   {

    int
time = 0;

    for(int
p = 0; p < num[i]; ++p)

    {

     if(
(car[i][p].start >= j
&& car[i][p].end >
j+k) ||

      (car[i][p].start
<= j &&
car[i][p].end < j+k) )

      continue;

     else

      time++;

    }

    dp[i+1][j+k]
= min(dp[i+1][j+k], dp[i][j]+time);

   }

  }

 }

}
int main()

{

 int i, j;

// freopen("input.txt", "r", stdin);

 while(scanf("%d %d", &n,
&m) != EOF)

 {

  int ni, Ti, ti;

  for(i = 0; i <
n; ++i)

   for(j = 0; j
<= n*600; ++j)

    dp[i][j]
= INF;
  memset(num, 0,
sizeof(num));

  for(i = 0; i <
m; ++i)

  {

   scanf("%d %d
%d", &ni, &Ti,
&ti);

   ni--;

   Ti =
change(Ti);

   car[ni][
num[ni] ].start = Ti;

   car[ni][
num[ni
4000
] ].end = ti+Ti;

   num[ni]++;

  }
  DP();
  int result =
INF;

  int time;

  for(i = n*300; i
<= n*600; ++i)

  {

   if(result
> dp
[i])

   {

    result
= dp
[i];

    time
= i;

   }

  }

  printf("%d\nd\n", result,
changeBack(time));

 }

 return 0;

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: