uva 301(回溯)

来源:互联网 发布:mysql 条件去重 编辑:程序博客网 时间:2024/05/21 03:28

题意:给出了每个车的最大载客量,从A到B共有几个站点,并且开始的订单数量,每个订单包括的起点和终点以及人数,订单的最后保留是不确定的,它由最大利润和最大载客量决定,求出最大利润(假定每个人经过一个站点收费加1)。

题解:第一次用全排列,订单的每种保留情况都算一下,最后得到利润最大的,结果超时,不管怎么剪枝都超时。。所以换成用一个数组保存每个站点当前的人数,然后判断如果保留的某个订单后没有超过最大载客量,就更新从这个订单的起点到终点(不包括终点)当前的人数,否则不更新,然后递归下一个订单,记得递归后如果站点人数是更新过的要去还原,运用了回溯的思想。

#include <stdio.h>const int N = 25;struct P {int sta, end, num;}p[N];int cap, m, n, maxx, count, now[N];void init() {for (int i = 0; i < N; i++) {p[i].sta = p[i].end = p[i].num = 0;now[i] = 0;//存储当前站点的人数}maxx = 0;}int judge(int ord) {for (int i = p[ord].sta; i < p[ord].end; i++)if ((now[i] + p[ord].num) > cap)//判断当前站点的人数加上这个订单上的人数是否达到上限return 0;return 1;}void dfs(int ord, int count) {if (count > maxx)maxx = count;if (ord >= n)return;if (judge(ord)) {for (int i = p[ord].sta; i < p[ord].end; i++)now[i] += p[ord].num;//记录了每一站的人数int temp = count + (p[ord].end - p[ord].sta) * p[ord].num;//更新收入dfs(ord + 1, temp);for (int i = p[ord].sta; i < p[ord].end; i++)//回溯,需要把之前加上的人数还原now[i] -= p[ord].num;}dfs(ord + 1, count);//如果不接受订单,搜索下一个订单}int main() {while (scanf("%d%d%d", &cap, &m, &n) && (cap || m || n) ) {init();for (int i = 0; i < n; i++)scanf("%d%d%d", &p[i].sta, &p[i].end, &p[i].num);dfs(0, 0);printf("%d\n", maxx);}return 0;}


0 0
原创粉丝点击