与网上其他DFS解法相似,但通过for循环实现是否接单:
大致思路相似:维持一个数组存储当前搜索状态的载客量,用takeOrder()函数实现两个功能:1.判断能否接单2.若能则改变状态,同时对于负的载客直接改变状态用于回溯,dfs()中用for循环遍历订单并且通过参数设置不会搜索已经搜过的订单,具体的实现方法见代码,运行时间大概800ms
#include<iostream>
#include<cstdio>
#include<cstring>
#define mem(a,b) memset(a, b, sizeof(a))
#define maxo 22*8 + 100
using namespace std;
int cap, num, nOrder;
int maxEarn;
int orderRecord[maxo];
bool vis[maxo];
struct Order{
int start, end;
int num;
}Or[maxo];
bool takeOrder(int s, int e, int n){//判断能否接单,若能则改变orderRecord
if(n > 0){
for(int i = s; i < e; i++){
if(orderRecord[i] + n > cap)
return false;
}
}
for(int i = s; i < e; i++){
orderRecord[i] += n;
}
return true;
}
void dfs(int oid, int curEarn){
if(oid >= nOrder) return;
int increaseEarn;
for(int i = oid; i < nOrder; i++){
if(takeOrder(Or[i].start, Or[i].end, Or[i].num)){
increaseEarn = (Or[i].end - Or[i].start) * Or[i].num;
if(curEarn + increaseEarn > maxEarn)
maxEarn = curEarn + increaseEarn;
dfs(i+1, curEarn + increaseEarn);
takeOrder(Or[i].start, Or[i].end, -Or[i].num);
}
}
}
int main(){
while(~scanf("%d%d%d", &cap, &num, &nOrder) && cap+num+nOrder!=0){
for(int i = 0; i < nOrder; i++){
scanf("%d%d%d", &Or[i].start, &Or[i].end, &Or[i].num);
}
mem(vis, false);
mem(orderRecord, 0);
maxEarn = 0;
dfs(0, 0);
printf("%d\n", maxEarn);
}
return 0;
}