DFS深度搜索算法实现深度探究解析-以POJ 1040为例

POJ 1040

Transportation

Time Limit: 1000MS

 

Memory Limit: 10000K

Total Submissions: 2872

 

Accepted: 1176

Description

Ruratania is just entering capitalism and is establishingnew enterprising activities in many fields in- cluding transport. Thetransportation company TransRuratania is starting a new express train from cityA to city B with several stops in the stations on the way. The stations aresuccessively numbered, city A station has number 0, city B station number m.The company runs an experiment in order to improve passenger transportationcapacity and thus to increase its earnings. The train has a maximum capacity npassengers. The price of the train ticket is equal to the number of stops(stations) between the starting station and the destination station (includingthe destination station). Before the train starts its route from the city A,ticket orders are collected from all onroute stations. The ticket order fromthe station S means all reservations of tickets from S to a fixed destinationstation. In case the company cannot accept all orders because of the passengercapacity limitations, its rejection policy is that it either completely acceptor completely reject single orders from single stations.

Write a program which for the given list of orders from single stations on theway from A to B determines the biggest possible total earning of theTransRuratania company. The earning from one accepted order is the product ofthe number of passengers included in the order and the price of their traintickets. The total earning is the sum of the earnings from all accepted orders.

Input

The inputfile is divided into blocks. The first line in each block contains threeintegers: passenger capacity n of the train, the number of the city B stationand the number of ticket orders from all stations. The next lines contain theticket orders. Each ticket order consists of three integers: starting station,destination station, number of passengers. In one block there can be maximum 22orders. The number of the city B station will be at most 7. The block where allthree numbers in the first line are equal to zero denotes the end of the inputfile.

Output

The output fileconsists of lines corresponding to the blocks of the input file except theterminating block. Each such line contains the biggest possible total earning.

Source

Central Europe 1995

DFS实现代码

#include <iostream>
#include <cstdlib>
#include <algorithm>
using namespace std;
#define maxm 23
#define maxn 8
int cap, n, m;
int ans;
int ocount;
int down[maxn];
struct Order{    
	int s, e, p;
}order[maxm];

int max(int a,int b){
	return a>b?a:b;
}
bool operator < (const Order &a, const Order &b){
    if (a.s == b.s)        
		return a.e < b.e;    
	return a.s < b.s;
}

void dfs(int i, int p, int money){   
	if (i == m){      
		ans = max(ans, money);      
		return;    
	} 
	if (i > 0)        
		for (int j = order[i - 1].s + 1; j <= order[i].s; j++)            
			p -= down[j]; 
	if (p + order[i].p <= cap) {       
		down[order[i].e] += order[i].p; //down[i]表示i号车站有多少人下车
		dfs(i + 1, p + order[i].p, money + order[i].p * (order[i].e - order[i].s));
		down[order[i].e] -= order[i].p;
	} 
	dfs(i + 1, p, money);
}

int main(){
	int i;
	while(cin>>cap>>n>>m,cap||n||m){
		for(i=0;i<m;i++){   
			scanf("%d%d%d", &order[i].s, &order[i].e, &order[i].p);        
		}
		sort(order,order+m);
		ans = 0;
		dfs(0,0,0);
		printf("%d\n",ans);
	}
	return 0;
}

本题DFS算法实现深度解析:

1、 对order数组排序,使得票的始发站升序排练,当始发站相同时,使得终点站升序排列,这样便于统计每张票的始发站处下车的人数。

2、 DFS递归函数返回有两种情况:其一是i==m时该条路径搜索结束返回结果到原始调用处;其二是执行到DFS末尾返回,也是返回到调用该次DFS函数处。注意区分34行与37行调用DFS函数的不同,开始选择第1、2、3票搜索路径的DFS函数调用情况如下图所示

:


第34行的DFS调用是考虑选择第i张票,继续深度搜索;第37行的DFS调用是考虑不选择第i张票(可能由于选第i张票超过了火车容量限制或者是前面的搜索选择完毕回溯)调用的地方不同,自然dfs函数返回的地方也不同。

      通过本题的分析,总结经验如下:

      算法学习最忌讳粗枝大叶,很多看似思想简单的算法实现成代码运行就有很多新的难题,比如深度搜索DFS的实现,有以下关键点:

     1、由于搜索过程高度重复化,一般写成递归函数,DFS函数里面写明返回条件,不同情况下不同的递归调用条件。

     2、 DFS函数的构造一般有一个变量记录当前搜索的位置(如本题中i记录了当前搜索到了第几张票的选择),另外若干变量保存需要一直维护状态变量(如本题中的p记录了当前火车上的人数,money记录了当前选择方案下的总钱数)

    3、 DFS发生回溯的时候,要注意恢复原来状态变量的值(又叫“恢复现场”),比如第35行      down[order[i].e] -=order[i].p; 这里是由于前面考虑选择第i张票的搜索路径已经搜索完毕,那么下面考虑不选择第i张票,恢复下车人数数组down的状态到不选第i张票的情况,在第37行直接去考察第i+1张票的选择情况。

      最后,对于调用及执行情况比较复杂的代码,用好VC等IDE单步调试,观察callback、watch等窗口中函数调用、关键变量值的变化是很重要的研究途径,调试工具要充分利用。有必要学习一下重要的调试技巧,对于加深对程序的理解有好处。



你可能感兴趣的:(算法,struct,express,callback,each,Numbers)