UVa 301 - Transportation

/*
回溯法
1、乘客限制。
2、当剩余所有票价加起来也不会超过最大价格则回溯。
AC:0.092s
*/
#include <iostream>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <algorithm>
using namespace std;
const int MAX_ORDERS = 22+2;
const int MAX_STOPS = 7+2;
struct order {
    int start;
    int destination;
    int passengers;
    int total_price;
};

order orders[MAX_ORDERS];
int n, m, ords;
int biggest_price;
int stops[MAX_STOPS]; //各站人数

//是否可以接受order
int can_take_order(int cur)
{
    for(int j=orders[cur].start; j<orders[cur].destination; j++) {
        stops[j] += orders[cur].passengers;
    }
    for(int i=0; i<m; i++) {
        if(stops[i] > n) return 0;
    }
    return 1;
}
//剩余票价加起来是否可以超过最大价格
int can_over(int cur, int price)
{
    int left_price = 0;
    for(int i=cur; i<ords; i++) {
        left_price += orders[i].total_price;
    }
    if(price+left_price <= biggest_price) {
        return 0;
    }
    return 1;
}

void dfs(int cur, int price)
{
    if(cur == ords) {
        if(price > biggest_price)
            biggest_price = price;
        return;
    }
    if(!can_over(cur, price)) return;

    int buff_stops[MAX_STOPS];
    memcpy(buff_stops, stops, sizeof(stops)); //保存
    if(can_take_order(cur)) {
        dfs(cur+1, price+orders[cur].total_price);
    }
    memcpy(stops, buff_stops, sizeof(buff_stops)); //恢复
    dfs(cur+1, price);
}

int main(void) {
    #ifndef ONLINE_JUDGE
    freopen("in.txt", "r", stdin);
    #endif
    while(scanf("%d%d%d", &n, &m, &ords) == 3) {
        if(m==0 && n==0 && ords==0) break;
        for(int i=0; i<ords; i++) {
            scanf("%d%d%d", &orders[i].start,
                  &orders[i].destination,
                  &orders[i].passengers);
            orders[i].total_price = (orders[i].destination -
                                     orders[i].start) *
                                     orders[i].passengers;
        }
        memset(stops, 0 ,sizeof(stops));
        biggest_price = 0;
        dfs(0, 0);
        printf("%d\n", biggest_price);
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值