第一次交,直接dfs超时。2^22这个数还是挺大的,所以得考虑剪枝。题剪枝的办法是在检查到一张票的时候,把剩下票的所有的利润值都试着累加起来再加上此刻的利润,跟之前存储的最大利润进行比较,如果最大利润还是比较大的话,那么就没有必要再递归下去了,反正最好的情况加起来都没有当前的最大利润大。
-----------------------摘自http://www.cnblogs.com/liaoguifa/archive/2013/04/25/3043183.html
#include <iostream>
#include <cstring>
#include<cstdio>
#include<cstdlib>
#include <string>
#include<algorithm>
//#define MARK -2147483647
using namespace std;
int cityn,ordn,capa,ans;int lirun[30];
struct ding
{
int s,t,num;int flag;
};
bool com(ding a,ding b)
{
return a.s<b.s;
}
ding d[30];
void dfs(int num,int ordi,int price)
{
int i;
if(ordi==ordn){if(price>ans) ans=price;return; }
int num1=num;
for(i=0;i<ordi;++i)
{
if(d[ordi].s>=d[i].t&&d[i].flag){num1=num1-d[i].num; }
}
if(ans>price+lirun[ordi])return;
if(num1+d[ordi].num>capa)
{dfs(num,ordi+1,price);}
else
{ dfs(num,ordi+1,price); //1 1移到2处并没有时间减少,本来以为先选,比先不选快。
d[ordi].flag=1;
dfs(num+d[ordi].num,ordi+1,price+(d[ordi].t-d[ordi].s)*d[ordi].num);
d[ordi].flag=0;
//2
}return;
}
int main()
{
// freopen("in.txt","r",stdin);
while(scanf("%d%d%d",&capa,&cityn,&ordn))
{
ans=0;
if(!cityn&&!capa&&!ordn)break;
int i;
for(i=0;i<ordn;++i)
{
scanf("%d%d%d",&d[i].s,&d[i].t,&d[i].num);
d[i].flag=0;
}
sort(d,d+ordn,com);lirun[ordn-1]=(d[ordn-1].t-d[ordn-1].s)*d[ordn-1].num;
for(i=ordn-2;i>=0;--i){lirun[i]=lirun[i+1]+(d[i].t-d[i].s)*d[i].num; }
dfs(0,0,0);
printf("%d\n",ans);
}
return 0 ;
}