您的位置:首页 > 其它

UVA 301 POJ 1040- Transportation DFS 回溯

2014-04-17 15:21 190 查看
这道题在UVA过了 但是在POJ上超时了  POJ1040  想一下另外一种算法怎么才能更快的计算出答案

POJ讨论中的优化思路

这道题感觉是个很好的 DFS 题目。 在车站一条线上进行搜索,回溯。

然而,如果不进行优化剪枝的话,肯定会TLE,我在本机使用前面一位
同学提供的数据,直接运行了一下你的程序,大约要2秒钟。。。

优化可以这么做:
1.calss A中可以增加两个域:
P---表示本次order的总价值,它等于  (终点-起点)*人数
R---表示选择本order后,剩余价值--即最多还可得到多大收益

2.读入n,m,l,对P降序排列后,在计算各个order的R,这样很明显的
结论就是:
假若我在某个车站展开DFS,如果"当前收益+该节点的R<max"则
直接在这个节点return,无需再往下搜索。就是在你的DFS循环
里的flag前面加上:if(total+p[i].R < max) return;

本机运行了一下,速度很快。 这里运行一下46ms
不知是否还能再进行优化剪枝?
或者使用C的输入输出,速度更快一点15ms,但这没啥意义。。。。。


UVA  POJ代码

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn = 100;
int N,M,NUM,MAX,Length,L;
int station[maxn],vis[maxn],sp[maxn];

struct ORDER
{
int st,ed,money,num;
}order[maxn];

void DFS(int S,int money,int Begin)///当前站点  当前钱数  开始递归计算的起点
{
if(money > MAX)MAX = money;
if(S >= M)return ;
for(int i = Begin; i < Length; i++)
{
if(order[i].st == S && vis[i] == 0)
{
int f = 1,minn = 0;
for(int j = S; j < order[i].ed; j++)
{
if(station[j] < order[i].num) f = 0; ///如果当前站的容量小于此订单人数就舍去 不处理当前订单  处理下一个订单
}
//if(sp[order[i].st] + money < MAX) f = 0;///加上这个优化  在UVA 过了 POJ也过了  547ms  但是还以再优化  继续想
if(f == 1)
{
for(int j = S; j < order[i].ed; j++)
{
station[j] -= order[i].num;///当前订单从起点到终点(不包含终点)每个站的容量减去当前订单人数
}
vis[i] = 1;
DFS(S,money + order[i].money, i +1);
vis[i] = 0;                 ///状态复原
for(int j = S; j < order[i].ed; j++)
station[j] += order[i].num;
}
}
else
if(order[i].st > S)break;
}
DFS(S+1,money,Begin);///当前站没有可取的了  从下一个站开始DFS
}

int main()
{
#ifdef LOCAL
freopen("in.txt","r",stdin);
#endif // LOCAL
while(scanf("%d%d%d",&N,&M,&Length))
{
if(N == 0 && M == 0 && Length == 0)break;
for(int i = 0; i <= M; i++)
{
station[i] = N;
sp[i] = N * (M - i);
}
memset(vis,0,sizeof(vis));///初始化每个站的容量为最大   并标记都没有访问过
for(int i = 0 ;i < Length; i++)
{
scanf("%d%d%d",&order[i].st,&order[i].ed,&order[i].num);
order[i].money = (order[i].ed - order[i].st) * order[i].num;
}
MAX = 0;
/*sort(order,order+Length,cmp);///结构体排序  为DFS做基础*////啊啊啊  次奥  sort排序不稳定  RE无数次
for (int i = 0;i < Length-1; i++)
for (int j = i+1;j < Length; j++)
{
if (order[i].st > order[j].st)
{
int t;
t = order[i].st; order[i].st = order[j].st; order[j].st = t;
t = order[i].money;  order[i].money = order[j].money;   order[j].money = t;
t = order[i].ed;   order[i].ed = order[j].ed;     order[j].ed = t;
t = order[i].num;   order[i].num = order[j].num;     order[j].num = t;
}
}
///因为开车的顺序是从小到大的  不会出现逆序的情况  所以按起点排序
DFS(0,0,0);
printf("%d\n",MAX);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  回溯 dfs 剪枝