POJ-1724 深搜剪枝
这道题目如果数据很小的话。我们通过这个dfs就可以完成深搜:
void dfs(int s)
{
	if (s==N)
	{
		minLen=min(minLen,totalLen);
		return ;
	}
	for (int i=0;i<G[s].size();i++)
	{
		Road r=G[s][i];
		if (r.t+totalCost>K)
			continue;
		if (!visited[r.d])
		{
			visited[r.d]=1;
			totalLen+=r.L;
			totalCost+=r.t;
			dfs(r.d);
			totalCost-=r.t;
			totalLen-=r.L;
			visited[r.d]=0;
		}
	}
}
我们可以看一下这个代码,意思就是说,如果找边的时候,我们已经搜索到了终点,也就是s==N的时候,我们就直接改写minLen,然后返回到上一层,进行totalCost,totalLen和visited数组的返回工作,因为我们这次走的是这一条路,当我们返回的时候,就将这条路的终点标记全部还原,因为从这条路的起始点还可能会有其它的路,如果不把它还原的话,其它的路就被封死了,深搜就无法进行的很完全了,不能说是遍历了。
我们对于以s为起点的边进行遍历,发现边r的花费加上之前的总花销已经超过K,总钱数了,我们就跳过这一条边,这是第一次剪枝。
如果我们没有访问过边r的终点d时,我们就把它访问位设置为1,总路程加上r边长,总花费加上r边的过路费,然后深搜d。
这是可以通过一些较小的数据的,但是这道题中的数据很大,而dfs中又做了很多的无用功,所以我们进行以下的剪枝:
如果d点没有被访问过,我们就判断如果这次走到点d的时候,总路程已经超过minLen了,也就是之前找到的最短路,我们就跳过这个终点的深搜,我们直接不走这条路了。
这个剪枝还是不够,所以我们拿空间换取时间,我们设置一个minL[110][10010]数组,minL[k][m]表示之前走到点k并且花费为m的最短长度。
如果我们这次走到点k,并且花销为m,但是我们的路程已经大于这个最短长度了,我们就跳出这重循环,执行循环的下一次。
因为它的意思,也就是说,我们每走过一个点,我们就进行一次比较,确保我们不花相同的钱,走更远的路,这个剪枝极为有效,直接可以过。
代码如下:
#include <iostream>
#include <vector>
#include <cstring>
using namespace std;
int N,K,R;
struct Road {
	int d,L,t;
};
vector < vector<Road> > G(110);
int minLen;
int minL[110][10010];
int totalLen;
int totalCost;
int visited[110];
void dfs(int s)
{
	if (s==N)
	{
		minLen=min(minLen,totalLen);
		return ;
	}
	for (int i=0;i<G[s].size();i++)
	{
		Road r=G[s][i];
		if (r.t+totalCost>K)
			continue;
		if (!visited[r.d])
		{
			if (totalLen+r.L>=minLen)
				continue;
			if (totalLen+r.L>=minL[r.d][r.t+totalCost])
				continue;
			visited[r.d]=1;
			totalLen+=r.L;
			minL[r.d][r.t+totalCost]=totalLen;
			totalCost+=r.t;
			dfs(r.d);
			totalCost-=r.t;
			totalLen-=r.L;
			visited[r.d]=0;
		}
	}
}
int main()
{
	cin>>K>>N>>R;
	for (int i=0;i<R;i++) {
		int s;
		Road r;
		cin>>s>>r.d>>r.L>>r.t;
		if (s!=r.d) {
			G[s].push_back(r);
		}
	}
	memset(visited,0,sizeof(visited));
	for (int i=0;i<110;i++) {
		for (int j=0;j<10010;j++) {
			minL[i][j]=1<<30;
		}
	}
	totalLen=0;
	totalCost=0;
	minLen=1<<30;
	visited[1]=1;
	dfs(1);
	if (minLen<(1<<30))
		cout<<minLen<<endl;
	else cout<<-1<<endl;
	return 0;
}												
											POJ-1724 深搜剪枝的更多相关文章
- POJ 2531  深搜剪枝
		
题意:全局最大割. 分析:有相应的算法,数据量很小,可以枚举源点,汇点,最大流. 这里用DFS,状态定义:分成两个集合,刚开始S集合全部点,然后一个一个放,这是一个回溯的过程. 没剪枝也过了. 剪枝技 ...
 - Hdu3812-Sea Sky(深搜+剪枝)
		
Sea and Sky are the most favorite things of iSea, even when he was a small child. Suzi once wrote: ...
 - 深搜+剪枝 POJ 1724 ROADS
		
POJ 1724 ROADS Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 12766 Accepted: 4722 D ...
 - poj1190 生日蛋糕(深搜+剪枝)
		
题目链接:poj1190 生日蛋糕 解题思路: 深搜,枚举:每一层可能的高度和半径 确定搜索范围:底层蛋糕的最大可能半径和最大可能高度 搜索顺序:从底层往上搭蛋糕,在同一层尝试时,半径和高度都是从大到 ...
 - UVA 10160 Servicing Stations(深搜 + 剪枝)
		
Problem D: Servicing stations A company offers personal computers for sale in N towns (3 <= N < ...
 - ACM 海贼王之伟大航路(深搜剪枝)
		
"我是要成为海贼王的男人!" 路飞他们伟大航路行程的起点是罗格镇,终点是拉夫德鲁(那里藏匿着"唯一的大秘宝"--ONE PIECE).而航程中间,则是各式各样的 ...
 - hdu 1518 Square(深搜+剪枝)
		
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1518 题目大意:根据题目所给的几条边,来判断是否能构成正方形,一个很好的深搜应用,注意剪枝,以防超时! ...
 - 一本通例题-生日蛋糕——题解<超强深搜剪枝,从无限到有限>
		
题目传送 显然是道深搜题.由于蛋糕上表面在最底层的半径确认后就确认了,所以搜索时的面积着重看侧面积. 找维度/搜索面临状态/对象:当前体积v,当前外表面面积s,各层的半径r[],各层的高度h[]. 可 ...
 - 模拟赛T5 : domino ——深搜+剪枝+位运算优化
		
这道题涉及的知识点有点多... 所以还是比较有意思的. domino 描述 迈克生日那天收到一张 N*N 的表格(1 ≤ N ≤ 2000),每个格子里有一个非 负整数(整数范围 0~1000),迈克 ...
 
随机推荐
- IEnumerable<T> 的时候一个主意事项p
			
IEnumerator IEnumerable.GetEnumerator() { return _vtDataView.GetEnumerator(); } public IEnumerator&l ...
 - python __builtins__ type类 (69)
			
69.'type', 返回对象类型 class type(object) | type(object_or_name, bases, dict) | type(object) -> the ob ...
 - 笔记-JavaWeb学习之旅2
			
数据库的基本概念 1.数据库:DataBase 简称 DB,用于存储和管理数据的仓库 特点: 1.持久化存储数据的,其实数据库就是一个文件系统, 2.方便存储和管理数据 3.使用了统一操作数据库 -- ...
 - 安装截图软件shutter
			
直接进入软件中心安装吧 不知道软件中心安装的软件可以apt upgrade 命令更新么 应该是可以的,感觉软件中心就是个图形化的apt和新立得差不多 shutter可以放大缩小截图, ctrl + 鼠 ...
 - oracle错误:1067进程意外终止
			
oracle错误:1067进程意外终止我Oracle安装完了之后可以运行的 ,过了一段时间不可以了,就上网找了一下,原来是自己的ip已经改变.我一直使用IP地址的. 将D:\oracle\produc ...
 - java高分局之jstat命令使用
			
S0C S1C S0U S1U EC EU OC OU MC MU CCSC CCSU YGC ...
 - [CQOI2014]通配符匹配
			
Description 几乎所有操作系统的命令行界面(CLI)中都支持文件名的通配符匹配以方便用户.最常见的通配符有两个,一个是星号(""'),可以匹配0个及以上的任意字符:另一个 ...
 - 164 Maximum Gap 最大间距
			
给定一个无序的数组,找出数组在排序后相邻的元素之间最大的差值.尽量尝试在线性时间和空间复杂度情况下解决此问题.若数组元素个数少于2,则返回0.假定所有的元素都是非负整数且范围在32位有符号整数范围内. ...
 - Jquary基础
			
基本知识: 就是一个JS函数包 选择器:基本选择器: 基本:ID选择器 “#” , Class选择器 “.”,标签选择器 “标签名” 组合:并列用“,”隔开 后代用空格隔开 过滤选择器:基本过滤: ...
 - eclipse搭建android开发环境详细步骤
			
搭建android应用的开发环境,一套程序下来也是相当繁琐的,这里我整理下一整套详细流程: 1,下载JDK 去oracle官网下载最新版本的jdk,官网地址 http://www.oracle.com ...