/*
* 要运送车辆到对岸.车辆已经排好队,注意因为桥窄不能超车,
* 分组的时候不能随意分组,前一组的车辆都排在后一组车辆的前
* 面,即车辆的顺序是按输入固定的。
* 只有一座单行的桥
*
* 每辆车有其重量及最最快车速
*
* 通过分组方式将车辆分成几组运输,
* 每次只能运一组运到对岸后第二组才能出发,
*
* 每组中车辆的总重量不能超过桥的载重量,
*
* 运输速度则取决于该组车辆中最慢的那辆
*
*问如何分组,运输最快
动态规划,从前向后,依次求出到i位置时的最优解,考i位置的时候,考虑i-1,i-2...
* 直到i - j加在一起超过了载重量,则所有这些位置可能性都需要考虑到。
*
* s(i) = min ( (s(i-1) + (i)time), s(i-2) + (i ,i -1)time .. ,s(i - j) + (i , i - 1, ...i - j + 1)time )
*
* w(i) + w(i-1) + ...w(i - j + 1) <= W
* w(i) +.. w(i - j) > w
*
* 可以优化,思路是贪心
* 考虑如果没有速度区别,应该是考虑i位置的时候向前,该组装的越多越好。
* 另外即使有速度不同,s(i) <= s(j),when i < j的事实存在。
* 据此可以优化。 不过优化之后代码稍麻烦,而且提交后发现和没优化用时一样的。 因为复杂度没变还是需要判断那么多,只不过少计算了点,可以再思考如何优化。
1 #include <stdio.h>
2
3 int b,l,n; //b the max weight the bridge can afford, l the bridge length, n cars to transport
4 double r[1001]; // 记录DP算法,到当前位置最优解的最短时间
5 int w[1001]; // 记录各车的重量
6 int s[1001]; // 记录各车的速度
7
8 void SolveDP()
9 {
10 l *= 60; //因为最后求分钟,速度是小时每千米,先*60一样的
11 r[0] = 0;
12
13 int speed, weight;
14 double time_best, time_now;
15
16 for (int i = 1; i <= n; i++) { //从1开始记录下标,r[0] = 0作为哨兵,便于程序统一处理
17
18 scanf("%d%d", &(w[i]), &(s[i]));
19
20 //第一种分组尝试,i单独一组
21 weight = w[i];
22 speed = s[i];
23 time_best = r[i - 1] + (double)l / (double)speed;
24
25 //尝试其它所有可能的包含i的分组
26 for (int j = i - 1; j && (weight += w[j]) <= b; j-- ){
27 if (s[j] < speed)
28 speed = s[j];
29
30 time_now = r[j - 1] + (double)l / (double)speed;
31 if (time_now < time_best)
32 time_best = time_now;
33
34 }
35 r[i] = time_best;
36 }
37 printf("%.1f\n", r[n]);
38 }
39
40 int main(int argc, char *argv[])
41 {
42 while (1) {
43
44 scanf("%d%d%d",&b, &l, &n);
45
46 if (b == 0 && l ==0 && n ==0)
47 break;
48
49 SolveDP();
50 }
51 return 0;
52 }
3 int b,l,n; //b the max weight the bridge can afford, l the bridge length, n cars to transport
4 double r[1001]; // 记录DP算法,到当前位置最优解的最短时间
5 int w[1001]; // 记录各车的重量
6 int s[1001]; // 记录各车的速度
7
8 void SolveDP()
9 {
10 l *= 60; //因为最后求分钟,速度是小时每千米,先*60一样的
11 r[0] = 0;
12
13 int speed, weight;
14 double time_best, time_now;
15
16 for (int i = 1; i <= n; i++) { //从1开始记录下标,r[0] = 0作为哨兵,便于程序统一处理
17
18 scanf("%d%d", &(w[i]), &(s[i]));
19
20 //第一种分组尝试,i单独一组
21 weight = w[i];
22 speed = s[i];
23 time_best = r[i - 1] + (double)l / (double)speed;
24
25 //尝试其它所有可能的包含i的分组
26 for (int j = i - 1; j && (weight += w[j]) <= b; j-- ){
27 if (s[j] < speed)
28 speed = s[j];
29
30 time_now = r[j - 1] + (double)l / (double)speed;
31 if (time_now < time_best)
32 time_best = time_now;
33
34 }
35 r[i] = time_best;
36 }
37 printf("%.1f\n", r[n]);
38 }
39
40 int main(int argc, char *argv[])
41 {
42 while (1) {
43
44 scanf("%d%d%d",&b, &l, &n);
45
46 if (b == 0 && l ==0 && n ==0)
47 break;
48
49 SolveDP();
50 }
51 return 0;
52 }
试图优化
1 #include <stdio.h>
2 const int MaxNum = 1001; //注意因为从1开始,所以需要1000 + 1
3 int b,l,n; //b the max weight the bridge can afford, l the bridge length, n cars to transport
4 double r[1001]; // 记录DP算法,到当前位置最优解的最短时间
5 int w[1001]; // 记录各车的重量
6 int s[1001]; // 记录各车的速度
7
8 void SolveDP()
9 {
10 l *= 60; //因为最后求分钟,速度是小时每千米,先*60一样的
11 r[0] = 0;
12
13 int speed, weight;
14 double time_best, time_now;
15
16 for (int i = 1; i <= n; i++) { //从1开始记录下标,r[0] = 0作为哨兵,便于程序统一处理
17
18 scanf("%d%d", &(w[i]), &(s[i]));
19
20 //第一种分组尝试,i单独一组
21 weight = w[i];
22 speed = s[i];
23 time_best = 1000000; //max TODO why need so large I thought 1000*60 will be OK since l < 1000 s > 1 ??
24
25 //尝试其它所有可能的包含i的分组,注意速度没有下降则肯定更多车辆更优
26 //因为s(i) <= s(j) when i < j ,因此只有速度下降时我们才计算一下到前面
27 //速度对应的最优时间和已有的最优时间对比
28 int j;
29 for (j = i - 1; j && (weight += w[j]) <= b; j-- ){
30 if (s[j] < speed) {
31 time_now = r[j] + (double)l / (double)speed; //分组
.j-1, j|| j + 1
i
32 if (time_now < time_best)
33 time_best = time_now;
34 speed = s[j]; // change group sppeed to the lower one
35 }
36 }
37
38 time_now = r[j] + (double)l / (double)speed; //still nedd to deal with the last
39
40 if (time_now < time_best)
41 r[i] = time_now;
42 else
43 r[i] = time_best;
44 }
45
46 printf("%.1f\n", r[n]);
47 }
48
49 int main(int argc, char *argv[])
50 {
51 while (1) {
52
53 scanf("%d%d%d",&b, &l, &n);
54
55 if (b == 0 && l ==0 && n ==0)
56 break;
57
58 SolveDP();
59 }
60 return 0;
61 }
3 int b,l,n; //b the max weight the bridge can afford, l the bridge length, n cars to transport
4 double r[1001]; // 记录DP算法,到当前位置最优解的最短时间
5 int w[1001]; // 记录各车的重量
6 int s[1001]; // 记录各车的速度
7
8 void SolveDP()
9 {
10 l *= 60; //因为最后求分钟,速度是小时每千米,先*60一样的
11 r[0] = 0;
12
13 int speed, weight;
14 double time_best, time_now;
15
16 for (int i = 1; i <= n; i++) { //从1开始记录下标,r[0] = 0作为哨兵,便于程序统一处理
17
18 scanf("%d%d", &(w[i]), &(s[i]));
19
20 //第一种分组尝试,i单独一组
21 weight = w[i];
22 speed = s[i];
23 time_best = 1000000; //max TODO why need so large I thought 1000*60 will be OK since l < 1000 s > 1 ??
24
25 //尝试其它所有可能的包含i的分组,注意速度没有下降则肯定更多车辆更优
26 //因为s(i) <= s(j) when i < j ,因此只有速度下降时我们才计算一下到前面
27 //速度对应的最优时间和已有的最优时间对比
28 int j;
29 for (j = i - 1; j && (weight += w[j]) <= b; j-- ){
30 if (s[j] < speed) {
31 time_now = r[j] + (double)l / (double)speed; //分组
32 if (time_now < time_best)
33 time_best = time_now;
34 speed = s[j]; // change group sppeed to the lower one
35 }
36 }
37
38 time_now = r[j] + (double)l / (double)speed; //still nedd to deal with the last
39
40 if (time_now < time_best)
41 r[i] = time_now;
42 else
43 r[i] = time_best;
44 }
45
46 printf("%.1f\n", r[n]);
47 }
48
49 int main(int argc, char *argv[])
50 {
51 while (1) {
52
53 scanf("%d%d%d",&b, &l, &n);
54
55 if (b == 0 && l ==0 && n ==0)
56 break;
57
58 SolveDP();
59 }
60 return 0;
61 }
标程