Transportation |
题目的意思是说列车从起始点开出的时候,他要收集每个站(包括起始站)的乘客的搭车订单,这些订单能够知道多少人从哪个站上车然后从哪个站下车。但由于列车载人的容量有限,它必须有所规划,即放弃有些站的订单票,在这样的情况下,求这列车能够得到的最大的利润值,单价是人从上车开始每经过一个站收权值为1的价格
做法先存储订票中的信息,再设一个数组表示[站1],[站2]... .... 中此刻装载人的数量,每次检查一张票(也就是决定要不要放弃站的订票)时,大的方面来说是有两种可能,要或者不要,因为你要求最大的利润这是一般的做法,首先假设不放弃这票,那么先判断这些人上车后在经过的站里能不能容纳下,即没有超过列车的给定的容量,这是可以考虑这票,累加利润后继续检查(递归)下一张订票,递归回来要复原,复原之后考虑放弃这张票,继续递归。
但第一次会发现会超时, 2^22这个数还是挺大的,所以得考虑剪枝,这题剪枝的办法是在检查到一张票的时候,把剩下票的所有的利润值都试着累加起来再加上此刻的利润,跟之前存储的最大利润进行比较,如果最大利润还是比较大的话,那么就没有必要再递归下去了,反正最好的情况加起来都没有当前的最大利润大
题目链接:
http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=24&page=show_problem&problem=237
1 #include<stdio.h> 2 #include<string.h> 3 #include<stdlib.h> 4 #define MAXN 24 5 typedef struct ticket{ 6 int from, to; 7 int price, people; 8 }ticket; 9 10 ticket route[MAXN]; 11 int visit[MAXN]; 12 int road[10]; 13 int max; 14 15 int judge(int cur, int n, int sum, int flag) 16 { 17 int i, temp; 18 for(temp=0,i=cur+flag; i<=n; ++i) 19 temp += route[i].price*route[i].people; 20 if(max > sum+temp) return 0; 21 else return 1; 22 } 23 24 int Traverse(int cur, int room, int n, int sum) 25 { 26 int temp, i, j, store1, store2, flag; 27 if(cur > n) 28 { 29 max = max > sum ? max : sum; 30 return sum; 31 } 32 flag = 1; 33 for(i=route[cur].from; i<route[cur].to; ++i) 34 { 35 if(road[i]+route[cur].people > room) 36 { 37 flag = 0; 38 break; 39 } 40 } 41 if(flag) 42 { 43 if(judge(cur, n, sum, 0)) 44 { 45 visit[cur] = -1; 46 for(i=route[cur].from; i<route[cur].to; ++i) road[i] += route[cur].people; 47 Traverse(cur+1,room, n, sum+route[cur].price*route[cur].people); 48 for(i=route[cur].from; i<route[cur].to; ++i) road[i] -= route[cur].people; 49 visit[cur] = 0; 50 } 51 } 52 if(judge(cur, n, sum, 1)) 53 Traverse(cur+1, room, n, sum); 54 return 0; 55 } 56 57 int main() 58 { 59 60 int num, city, order, i, cnt; 61 while(scanf("%d%d%d", &num, &city, &order) != EOF) 62 { 63 if(!num && !city && !order) break; 64 memset(visit, 0, sizeof(visit)); 65 memset(road, 0, sizeof(road)); 66 for(i=1; i<=order; ++i) 67 { 68 scanf("%d%d%d", &route[i].from, &route[i].to, &route[i].people); 69 route[i].price = route[i].to - route[i].from; 70 } 71 max = -1; 72 cnt = 0; 73 Traverse(1, num, order, cnt); 74 printf("%d\n", max); 75 } 76 return 0; 77 }
我的第一种做法并不是这样的,看起来好像复杂了不少,首先我先将票的信息根据票中的车站的终点(第一关键字)和站的起点(第二关键字)进行排序,还是一张票一张票检测,但检测的时候我先看这张票的起点,根据起点判断之前已接纳的票中是否有早已到达站的或者刚好达到站的,这时暂且将这些人数减掉已腾出载人的空间,这时将当前站需要上车的人数加上去看能否小于或等于车的容纳量,如果可以,加上上面所说的剪枝后递归下一张票,递归回来的后将刚才的暂且减掉的人数加回去,继续递归
不知道当初为什么会有这样的思路,根据是什么都不清楚,但测试了几组数据都没测出来,大神们可以看看
1 #include<stdio.h> 2 #include<string.h> 3 #include<stdlib.h> 4 #define MAXN 24 5 typedef struct ticket{ 6 int from, to; 7 int price, people; 8 }ticket; 9 10 ticket route[MAXN]; 11 int visit[MAXN]; 12 int max; 13 14 15 16 int cmp(const void *a, const void *b) 17 { 18 int temp = (*(ticket *)a).to - (*(ticket *)b).to; 19 if(temp == 0) 20 return (*(ticket *)a).from - (*(ticket *)b).from; 21 return temp; 22 } 23 24 int judge(int cur, int n, int sum, int flag) 25 { 26 int i, temp; 27 for(temp=0,i=cur+flag; i<=n; ++i) 28 temp += route[i].price*route[i].people; 29 if(max > sum+temp) return 0; 30 else return 1; 31 } 32 33 int Traverse(int cur, int room, int n, int sum) 34 { 35 int temp, i, j; 36 if(cur > n) 37 { 38 max = max > sum ? max : sum; 39 40 /* printf("max = %d sum = %d room = %d\n", max, sum, room); 41 for(i=1; i<=n; ++i) 42 printf("visit[%d] = %d\n", i, visit[i]); 43 printf("\n"); */ 44 return 0; 45 } 46 47 for(i=1, temp=0; i<cur; ++i) 48 { 49 if(visit[i] == -1 && route[i].to <= route[cur].from) 50 { 51 temp += route[i].people; 52 visit[i] = cur; 53 } 54 } 55 56 if(room+temp - route[cur].people >= 0) 57 { 58 visit[cur] = -1; 59 if(judge(cur, n, sum, 0)) 60 Traverse(cur+1, room+temp-route[cur].people, n, sum+route[cur].price*route[cur].people); 61 } 62 63 for(i=1; i<cur; ++i) 64 if(visit[i] == cur && route[i].to <= route[cur].from) visit[i] = -1; 65 visit[cur] = 0; 66 if(judge(cur, n, sum, 1)) 67 Traverse(cur+1, room, n, sum); 68 return 0; 69 } 70 71 int main() 72 { 73 /* freopen("input.txt", "r", stdin); */ 74 int num, city, order, i, cnt; 75 while(scanf("%d%d%d", &num, &city, &order) != EOF) 76 { 77 if(!num && !city && !order) break; 78 memset(visit, 0, sizeof(visit)); 79 for(i=1; i<=order; ++i) 80 { 81 scanf("%d%d%d", &route[i].from, &route[i].to, &route[i].people); 82 route[i].price = route[i].to - route[i].from; 83 } 84 qsort(route+1, order, sizeof(ticket), cmp); 85 /* for(i=1; i<=order; i++) printf("%d %d\n", route[i].from, route[i].to); */ 86 max = cnt = 0; 87 Traverse(1, num, order, cnt); 88 printf("%d\n", max); 89 } 90 return 0; 91 }