• poj1040 Transportation(DFS)


    题目链接

    http://poj.org/problem?id=1040

    题意

    城市A,B之间有m+1个火车站,第一站A站的编号为0,最后一站B站的编号为m,火车最多可以乘坐n人。火车票的票价为票上终点站的编号减去起点站的编号。输入火车票订单的数目orderNums,接着输入orderNums个订单,每个订单由3个数字s,e,p组成,分别表示订单的起点站,终点站,该订单的人数,必须全部接受订单上的乘客或者全部不接受,求铁路公司最多可以赚多少钱。

    思路

    对于一个订单来说,有两种情况:接受和不接受。我们只需将所有可能的情况枚举出来,然后求在每一种情况下,铁路公司所赚的钱的最大值即可,这种枚举很适合使用dfs来解决。为了简化求解,我们要保证乘客是按火车站的编号顺序来上车,所以要将订单按订单起点的编号从低到高排序,若起点相同,则按终点编号从低到高排序。

    代码

     1 #include <algorithm>
     2 #include <iostream>
     3 #include <cstring>
     4 #include <cstdio>
     5 #include <vector>
     6 using namespace std;
     7 
     8 struct Order
     9 {
    10     int s;  //起点
    11     int e;  //终点
    12     int p;  //人数
    13 
    14     Order(int s, int e, int p):s(s), e(e), p(p){}
    15 };
    16 
    17 bool cmp(Order o1, Order o2)    //将订单排序
    18 {
    19     if(o1.s==o2.s)
    20         return o1.e<o2.e;
    21     return o1.s<o2.s;
    22 }
    23 
    24 const int N = 10;
    25 vector<Order> orders;
    26 int n, m, orderNums;
    27 int down[N];    //down[i]表示第i站下车的人数
    28 int ans;
    29 
    30 /*
    31 * p : 当前车上的人数
    32 * cur : 当前处理第cur个订单
    33 * sum : 当前赚的钱数
    34 */
    35 void dfs(int p, int cur, int sum)
    36 {
    37     if(cur==orderNums)
    38     {
    39         ans = max(ans, sum);
    40         return;
    41     }
    42 
    43     if(cur>0)   //减去上一个订单的下车人数
    44     {
    45         for(int i=orders[cur-1].s+1; i<=orders[cur].s; i++)
    46             p-=down[i]; //减去下车的人数
    47     }
    48     if(p+orders[cur].p <= n)
    49     {
    50         down[orders[cur].e] += orders[cur].p;
    51         dfs(p+orders[cur].p, cur+1, sum + (orders[cur].e-orders[cur].s)*orders[cur].p);
    52         down[orders[cur].e] -= orders[cur].p;   //注意恢复现场,便于回溯
    53     }
    54     dfs(p, cur+1, sum);
    55 }
    56 
    57 int main()
    58 {
    59     //freopen("poj1040.txt", "r", stdin);
    60     while(cin>>n>>m>>orderNums && n)
    61     {
    62         ans = -1;
    63         orders.clear();
    64         memset(down, 0, sizeof(down));
    65         for(int i=0; i<orderNums; i++)
    66         {
    67             int s, e, p;
    68             cin>>s>>e>>p;
    69             orders.push_back(Order(s, e, p));
    70         }
    71 
    72         sort(orders.begin(), orders.end(), cmp);
    73         dfs(0, 0, 0);
    74         cout<<ans<<endl;
    75     }
    76     return 0;
    77 }

     一点思考

    除了上面代码中的dfs写法,还可以换一种dfs写法,思路是在循环遍历订单时进行dfs,我感觉这种方法比上一种dfs方法要容易想一点,但实现起来比上一种要麻烦一些。代码和上面的代码基本一样,只是dfs函数有所不同。代码如下:

     1 #define _CRT_SECURE_NO_WARNINGS
     2 #include <algorithm>
     3 #include <iostream>
     4 #include <cstring>
     5 #include <cstdio>
     6 #include <vector>
     7 using namespace std;
     8 
     9 struct Order
    10 {
    11     int s;  //起点
    12     int e;  //终点
    13     int p;  //人数
    14 
    15     Order(int s, int e, int p) :s(s), e(e), p(p) {}
    16 };
    17 
    18 bool cmp(Order o1, Order o2)    //将订单排序
    19 {
    20     if (o1.s == o2.s)
    21         return o1.e<o2.e;
    22     return o1.s<o2.s;
    23 }
    24 
    25 const int N = 10;
    26 vector<Order> orders;
    27 int n, m, orderNums;
    28 int down[N];    //down[i]表示第i站下车的人数
    29 int ans;
    30 
    31 /*
    32 * p : 当前车上的人数
    33 * pre : 当前处理订单的上一个接受订单
    34 * cur : 当前处理第cur个订单
    35 * sum : 当前赚的钱数
    36 */
    37 void dfs(int p, int pre, int cur, int sum)
    38 {
    39     if (cur>0 && cur<orderNums)   //减去上一个订单的下车人数
    40     {
    41         for (int i = orders[pre].s + 1; i <= orders[cur].s; i++)
    42             p -= down[i]; //减去下车的人数
    43     }
    44     for (int i = cur; i<orderNums; i++)
    45     {
    46         bool flag = false;
    47         for (int j = orders[cur].s + 1; j <= orders[i].s; j++)    //测试是否能接受订单i
    48         {
    49             p -= down[j]; //减去下车的人数 (位置1)
    50             flag = true;
    51         }
    52         if (p + orders[i].p <= n)
    53         {
    54             pre = i;
    55             down[orders[i].e] += orders[i].p;
    56             dfs(p + orders[i].p, pre, i + 1, sum + (orders[i].e - orders[i].s)*orders[i].p);
    57             down[orders[i].e] -= orders[i].p;   //注意恢复现场,便于回溯
    58         }
    59         if (flag)    //只有在位置1减了的情况下再加回来
    60         {
    61             for (int j = orders[cur].s + 1; j <= orders[i].s; j++)
    62                 p += down[j]; //加上位置1减去的人数,恢复现场,便于回溯
    63         }
    64     }
    65     ans = max(ans, sum);
    66 }
    67 
    68 int main()
    69 {
    70     //freopen("poj1040.txt", "r", stdin);
    71     while (cin >> n >> m >> orderNums && n)
    72     {
    73         ans = -1;
    74         orders.clear();
    75         memset(down, 0, sizeof(down));
    76         for (int i = 0; i<orderNums; i++)
    77         {
    78             int s, e, p;
    79             cin >> s >> e >> p;
    80             orders.push_back(Order(s, e, p));
    81         }
    82 
    83         sort(orders.begin(), orders.end(), cmp);
    84         dfs(0, 0, 0, 0);
    85         cout << ans << endl;
    86     }
    87     return 0;
    88 }

    这份代码提交后内存占用与第一份代码相同,时间上稍微慢了一点点。

  • 相关阅读:
    HTML <form> 标签的 accept-charset 属性
    SpringMVC中Controller跳转到另一个Controller方法
    DIV层+CSS实现锁屏
    工作组模式下专用队列(Private Queue)如何引用远程队列路径
    stl之deque双端队列容器
    百度之星资格赛——Disk Schedule(双调旅行商问题)
    android 无线模式下使用ADB调试
    HDU
    NoSQL 数据库产品学习总结(一)
    ThinkPad E431怎样关闭触摸板
  • 原文地址:https://www.cnblogs.com/sench/p/7821626.html
Copyright © 2020-2023  润新知