/* |
2013腾讯马拉松初赛第5场 |
1002 威威猫系列故事——拼车记 |
|
Time Limit: 0.2 Seconds Memory Limit: 65536K |
|
话说威威猫有一次去参加比赛,虽然学校离比赛地点不太远,但威威猫还是想坐出租车去。大学城的出租车总是比较另类,有“拼车”一说,也就是说,你一个人坐车去,还是一堆人一起,总共需要支付的钱是一样的(每辆出租上除司机外最多坐下4个人)。刚好那天同校的一群Acmer在校门口扎堆了,大家果断决定拼车去赛场。 |
问题来了,一辆又一辆的出租车经过,但里面要么坐满了乘客,要么只剩下一两个座位,众Acmer都觉得坐上去太亏了,威威猫也是这么想的。 |
假设N名Acmer准备拼车,此时为0时刻,从校门到目的地需要支付给出租车师傅D元(按车次算,不管里面坐了多少Acmer),假如S分钟后恰能赶上比赛,那么S分钟后经过校门口的出租车自然可以忽略不计了。现在给出在这S分钟当中经过校门的所有的K辆出租车先后到达校门口的时间Ti 及里面剩余的座位Zi (1 <= Zi <= 4),Acmer可以选择上车几个人(不能超过),当然,也可以选择上0个人,那就是不坐这辆车。 |
俗话说,时间就是金钱,这里威威猫把每个Acmer在校门等待出租车的分钟数等同于花了相同多的钱(例如威威猫等待了20分钟,那相当于他额外花了20元钱)。 |
在保证所有Acmer都能在比赛开始前到达比赛地点的情况下,聪明的你能计算出他们最少需要花多少元钱么? |
Input |
输入第一行为T,表示有T组测试数据。 |
每组数据以四个整数N , K , D , S开始,具体含义参见题目描述,接着K行,表示第i辆出租车在第Ti分钟到达校门,其空余的座位数为Zi(时间按照先后顺序)。 |
[Technical Specification] |
T <= 50 |
N <= 100 |
K <= 100 |
D <= 100 |
S <= 100 |
1 <= Zi <= 4 |
1<= T(i) <= T(i+1) <= S |
Output |
对于每组测试数据,输出占一行,如果他们所有人能在比赛前到达比赛地点,则输出一个整数,代表他们最少需要花的钱(单位:元),否则请输出“impossible”。 |
Sample Input |
1 |
2 2 10 5 |
1 1 |
2 2 |
Sample Output |
14 |
*/ |
/* |
思路: |
DP题: |
假设f[i][j]为剩余i个人、剩余j辆车时的最小花费。 |
状态转换方程:f[i][j]=Min{f[i][j+1]+(t[K-j]-t[K-j-1])*i,Min{f[i+k][j+1]+(i+k)*(t[K-j]-t[K-j-1])+D}} |
1<=k<=z[K-j] |
K为总的车数。由于第j辆车可以做0~z[j]个人,所以有f[i+k][j+1]+(i+k)*(t[K-j]-t[K-j-1]。(不确保局部最优就是全局最优,所以不能用贪心)。 |
转自:ckl_soft的专栏 |
*/ |
#include <iostream> |
#include <cstdio> |
using namespace std; |
#define Min(x,y) ((x)<(y)?(x):(y)) |
int t[105] = {0}, z[105] = {0}, f[105][105], SUM[105] = {0}, tt; |
int main() { |
int i, j, n, k, d, txt, s, K, sum, zz; |
scanf ( "%d" , &txt); |
while (txt--) { |
sum = 0; |
scanf ( "%d%d%d%d" , &n, &K, &d, &s); |
for (i = 1; i <= K; ++i) { |
scanf ( "%d%d" , &tt, &zz); |
if (tt > s || zz <= 0) //不要超时的车 |
continue ; |
t[i] = tt; |
z[i] = zz; |
sum += z[i]; |
} |
for (i = K; i >= 1; --i) |
SUM[i] = SUM[i + 1] + z[i]; |
if (sum < n) { |
printf ( "impossible\n" ); |
continue ; |
} |
memset (f, 127, sizeof (f)); |
f[n][K] = 0; |
for (i = n; i >= 0; --i) { |
for (j = K; j >= 0; --j) { |
if ((n == i && j == K) || i > SUM[K - j]) continue ; //当后面所有车的载人数加起来都不够当前人数 |
tt = t[K - j] - t[K - j - 1]; |
f[i][j] = f[i][j + 1] + tt * i; |
for (k = 1; k <= z[K - j]; ++k) |
if (f[i][j] > f[i + k][j + 1] + (i + k)*tt + d) |
f[i][j] = f[i + k][j + 1] + (i + k) * tt + d; |
} |
} |
printf ( "%d\n" , f[0][0]); |
} |
return 0; |
} //2139062143 |
/*** |
3 |
1 3 10 2 |
1 0 |
4 0 |
5 1 |
*/ |
by: 发表于:2017-08-11 10:08:04 顶(0) | 踩(0) 回复
??
回复评论