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;
}
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;
}
相关文章推荐
- ACM: 金华赛区题目 水题…
- ACM: 动态规划题 poj&nb…
- ACM: 动态规划题 《黑书…
- ACM: 动态规划题 sicily…
- ACM: 图论题 poj 1…
- ACM: 图论题 poj 1466 最大独立团
- ACM: 图论题 poj 1…
- 图论: 差分约束系统
- ACM: 图论题 poj 1275 差分约束题
- ACM: 图论题 poj 1236 强连通
- ACM: 图论题 poj 1149 网络流问题
- ACM: 图论题 poj 1201 差分约束
- ACM: 搜索题 poj 1020
- ACM: 图论题 poj 3308 最大流问题
- Android的自定义控件起步
- ACM: 图论题 poj 3177 同 3352
- dos批处理中%~dp0%的说明
- ACM: 图论题 poj 2186 强连通分量
- ACM: 博弈题 poj 1143 状态压缩
- 本周学习的代码(数构 深度 广度 优先遍历)