pat 1003 Emergency (值得重点回顾)

16 篇文章 0 订阅
6 篇文章 0 订阅

一开始看错题意,题意是要求单源点对最短路径数和最大的点权重之和。知道要用dijskra算法,但为了求最短路径数,还得用深搜,依次把点加入集合中,若路径长度=最短路径值时,路径数+1。同时求出最大的点权重之和。

递归函数{
出口条件处理(最低级的情况);
return ...;
从第1列的8个位置{
依次尝试设置格子及限制区域
向下级递归
复原上一次尝试
}
};


AC代码:

#include<iostream>
using namespace std;
const int INF=1000000;
const int NUM=505;
int map[NUM][NUM];
int team[NUM],isVisit[NUM];
int dist[NUM];
int ans,maxTeamNum;

void init()
{
	int i,j;
	for(i=0;i<NUM;i++){
		isVisit[i]=0;
		team[i]=0;
		dist[i]=INF;
		for(j=0;j<NUM;j++){
			if(j!=i){
				map[i][j]=INF;//初始化为无穷大,表示不连通
				map[j][i]=INF;
			}

		}
	}
}
void dijskra(int n,int source)
{
	
	int i,minDis=INF,index=0,j;
	for(i=0;i<n;i++){
		dist[i]=map[source][i];
	}
	isVisit[source]=1;//将其加入已访问点的集合
	for(i=0;i<n-1;i++){
		minDis=INF;
		index=0;
		for(j=0;j<n;j++){
			if(!isVisit[j]&&dist[j]<minDis){//找到最小距离点
				minDis=dist[j];
				index=j;
			}
		}
		isVisit[index]=1;//将其加入已访问点的集合
		for(j=0;j<n;j++){//更新源点与每个点之间的距离
			if(map[index][j]<INF&&dist[j]>dist[index]+map[index][j])
				dist[j]=dist[index]+map[index][j];
		}
	}
	
	
}

void dfs(int n,int cId,int dest,int curDis,int curTeamNum)
{
	int i;
	isVisit[cId]=1;
	if(cId==dest){
		if(curDis==dist[dest]){
			ans++;//最短路径数+1
			if(curTeamNum>maxTeamNum)
				maxTeamNum=curTeamNum;
		}
		return;
	} 
	if(curDis>dist[dest])//当前的路径长度已经超过最短路径,就没有必要继续搜索了。
		return;
	for(i=0;i<n;i++){
		if(!isVisit[i]&&map[cId][i]<INF){//城市i未被访问过,且cId到i连通
			dfs(n,i,dest,curDis+map[cId][i],curTeamNum+team[i]);
			isVisit[i]=0;
		}
	}
}

int main()
{
	int n,m,source,dest,i;
	int c1,c2,l;
	freopen("C:\\Documents and Settings\\Administrator\\桌面\\input.txt","r",stdin);

	cin>>n>>m>>source>>dest;
	init();
	for(i=0;i<n;i++)
		cin>>team[i];
	for(i=0;i<m;i++){
		cin>>c1>>c2>>l;
		map[c1][c2]=l;
		map[c2][c1]=l;
	}
	dijskra(n,source);
	for(i=0;i<n;i++)
		isVisit[i]=0;
	dfs(n,source,dest,0,team[source]);
	cout<<ans<<" "<<maxTeamNum<<endl;
	return 0;


}

DFS递归的基本套路:



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值