漫步校园--(bfs+dfs)最短距离+记忆化搜索

LL最近沉迷于AC不能自拔,每天寝室、机房两点一线。由于长时间坐在电脑边,缺乏运动。他决定充分利用每次从寝室到机房的时间,在校园里散散步。整个HDU校园呈方形布局,可划分为n*n个小方格,代表各个区域。例如LL居住的18号宿舍位于校园的西北角,即方格(1,1)代表的地方,而机房所在的第三实验楼处于东南端的(n,n)。因有多条路线可以选择,LL希望每次的散步路线都不一样。另外,他考虑从A区域到B区域仅当存在一条从B到机房的路线比任何一条从A到机房的路线更近(否则可能永远都到不了机房了…)。现在他想知道的是,所有满足要求的路线一共有多少条。你能告诉他吗?
Input
每组测试数据的第一行为n(2=<n<=50),接下来的n行每行有n个数,代表经过每个区域所花的时间t(0<t<=50)(由于寝室与机房均在三楼,故起点与终点也得费时)。
Output
针对每组测试数据,输出总的路线数(小于2^63)。
Sample Input
3
1 2 3
1 2 3
1 2 3
3
1 1 1
1 1 1
1 1 1
Sample Output
1
6

这个题的意思不太好理解,其实就是求最短路径,因为可能会超时,所以要记忆化搜索,首先先对终点先bfs,求出最短距离,然后在进行搜索。注意搜索结果要用long long 去存

#include<bits/stdc++.h>

using namespace std;
const int N=100;
int n;
int tu[N][N];
int dis[N][N];
int d[4][2]={0,1,1,0,0,-1,-1,0};

struct peo{
	int x,y;
};
void bfs(int x,int y) 
{//bfs模板 
	queue<peo> que;
	peo t,tt;
	t.x=x;t.y=y;
	que.push(t);
	dis[x][y]=tu[x][y];//注意“上  下楼”也算时间 
	while(!que.empty()){
		t=que.front();
		que.pop();
		for(int i=0;i<4;i++){
			int dx=t.x+d[i][0];tt.x=dx;
			int dy=t.y+d[i][1];tt.y=dy;
			if(dx>=0&&dx<n&&dy>=0&&dy<n&&dis[t.x][t.y]+tu[dx][dy]<dis[dx][dy]){//dx,dy对应距离大于x,y+上一个点到达该点的距离,对应两种情况,
				//还未遍历或者不是最短距离,两种情况都应该更新此点距离。 
				dis[dx][dy]=dis[t.x][t.y]+tu[dx][dy];//更新距离 
				que.push(tt);
			}
		}
	}
}
long long dp[N][N];//记忆化数组 
long long dfs(int x,int y)
{
	if(dp[x][y])return dp[x][y];//如果遍历过就直接返回结果 
	for(int i=0;i<4;i++){
		int dx=x+d[i][0];
		int dy=y+d[i][1];
		if(dx>=0&&dx<n&&dy>=0&&dy<n&&dis[dx][dy]<dis[x][y])
		{
			dp[x][y]+=dfs(dx,dy);
		}
	}
	return dp[x][y];//保存此次结果 
}
int main()
{
	while(cin>>n)
	{
		for(int i=0;i<n;i++)
		for(int j=0;j<n;j++)
		{
			scanf("%d",&tu[i][j]);
			dis[i][j]=0x3f3f3f3f;//初始化为最大值 
		}
		bfs(n-1,n-1);//对终点进行bfs,用dis数组进行保存距离 
		memset(dp,0,sizeof(dp));//初始化为0 
		dp[n-1][n-1]=1;//dp存的是该点到终点路的条数 
		dfs(0,0);
		
		printf("%lld\n",dp[0][0]);
	}
	return 0;
}

#include #include #include #define INFINITY 10000 //最大值 #define MAX_V 30 //最大顶点个数 typedef struct{ char* vexs[MAX_V]; //顶点向量 int arcs[MAX_V][MAX_V];//邻接矩阵 int vexnum,arcnum;//图的当前顶点数和弧数 }MGraph; int have[30]; int CreateUDN(MGraph &G) {//采用数组(邻接矩阵)表示法,构造无向网G. int i = 0,j=0; G.vexnum = 17; G.arcnum = 10; G.vexs[0] = "银杏苑"; G.vexs[1] = "邓安堂楼"; G.vexs[2] = "紫荆苑"; G.vexs[3] = "紫薇苑"; G.vexs[4] = "碧桂苑"; G.vexs[5] = "东楼(美术楼)"; G.vexs[6] = "行政楼"; G.vexs[7] = "西楼(中文楼)"; G.vexs[8] = "第四饭堂"; G.vexs[9] = "图书馆"; G.vexs[10] = "黎灿活动中心"; G.vexs[11] ="英东生物工程学院"; G.vexs[12] = "青年湖"; G.vexs[13] = "信息工程学院"; G.vexs[14] = "体育馆"; G.vexs[15] = "丹桂苑"; G.vexs[16] = "南区大门"; for(i=0;i<G.vexnum;i++) for(j=0;j<G.vexnum;j++){if(i==j)G.arcs[i][j]=0;else G.arcs[i][j]=INFINITY;} G.arcs[0][3] = G.arcs[3][0] = G.arcs[0][2] = G.arcs[2][0] = 50 ; //为每一条边赋权 G.arcs[2][5] = G.arcs[5][2] = G.arcs[3][5] = G.arcs[5][3] = 150; G.arcs[2][8] = G.arcs[8][2] = G.arcs[3][8] = G.arcs[8][3] = 150; G.arcs[1][2] = G.arcs[2][1] = G.arcs[1][3] = G.arcs[3][1] = 100; G.arcs[1][4] = G.arcs[4][1] = 50; G.arcs[1][12] = G.arcs[12][1] = 300; G.arcs[2][3] = G.arcs[3][2] = 20; G.arcs[0][4] = G.arcs[4][0] = 90; G.arcs[5][6] = G.arcs[6][5] = 40; G.arcs[5][10] = G.arcs[10][5] = 50; G.arcs[5][16] = G.arcs[16][5] = 100; G.arcs[6][7] = G.arcs[7][6] = 40; G.arcs[6][8] = G.arcs[8][6] = 50; G.arcs[7][8] = G.arcs[8][7] = 25; G.arcs[7][9] = G.arcs[9][7] = 200; G.arcs[7][13] = G.arcs[13][7] = 150; G.arcs[7][16] = G.arcs[16][7] = 100; G.arcs[8][9] = G.arcs[9][8] = 50; G.arcs[9][11] = G.arcs[11][9] = 50; G.arcs[10][12] = G.arcs[12][10] = 300; G.arcs[12][15] = G.arcs[15][12] = 100; G.arcs[13][14] = G.arcs[14][13] = 50; G.arcs[14][15] = G.arcs[15][14] = 150; return 1; } void ShortPath(MGraph &G,int v0,int p[30][30],int d[]){ //迪杰斯特拉发求最短路径 int v,w,i,j,min;int final[MAX_V];int k=1; for(v=0;v<G.vexnum;++v){//初始化 final[v]=0; d[v]=G.arcs[v0-1][v]; for(w=0;w<G.vexnum;++w) p[v][w]=0; if(d[v]<INFINITY) {p[v][v0-1]=1;p[v][v]=1;} } d[v0-1]=0;final[v0-1]=1;have[0]=v0-1; for(i=1;i<G.vexnum;++i){//其余的vexnum-1个顶点 min=INFINITY; for(w=0;w<G.vexnum;++w) if(!final[w]) if(d[w]<min)//如有W点离更近 {v=w;min=d[w];} final[v]=1;have[k]=v;k++; for(w=0;w<G.vexnum;++w)//更新当前最短路径及距离 if(!final[w]&&(min+G.arcs[v][w]<d[w])) { d[w]=min+G.arcs[v][w]; for(j=0;j<G.vexnum;j++) {p[w][j]=p[v][j];} p[w][w]=1; } } } void main() { MGraph G;int v0,i,end;int P[MAX_V][MAX_V];int D[MAX_V];char *vexs[20];int ctr; cout<<"********************************************************************************"<<endl; cout<<" 欢迎光临韶关学院,祝旅程愉快!"<<endl; cout<<" 韶关学院校园导游系统为你服务!"<<endl; cout<<" 请选择你的出发点与所要到达的地方"<<endl; cout<<"********************************************************************************"<<endl; while(ctr!=0){ cout<<"(1) 银杏苑"<<" (2) 邓安堂楼"<<" (3) 紫荆苑"<<endl; cout<<"(4) 紫薇苑"<<" (5) 碧桂苑"<<" (6) 东楼(美术楼) "<<endl; cout<<"(7) 行政楼"<<" (8) 西楼(中文楼)"<<" (9) 第四饭堂 "<<endl; cout<<"(10) 图书馆"<<" (11) 黎灿学生活动中心"<<" (12) 英东生物工程学院"<<endl; cout<<"(13) 青年湖"<<" (14) 信息工程学院"<<" (15) 体育馆"<<endl; cout<<"(16) 丹桂苑"<<" (17) 南区大门"<<endl; vexs[0] = "银杏苑"; vexs[1] = "邓安堂楼"; vexs[2] = "紫荆苑"; vexs[3] = "紫薇苑"; vexs[4] = "碧桂苑"; vexs[5] = "东楼(美术楼)"; vexs[6] = "行政楼"; vexs[7] = "西楼(中文楼)"; vexs[8] = "第四饭堂"; vexs[9] = "图书馆"; vexs[10] = "黎灿学生活动中心"; vexs[11] ="英东生物工程学院"; vexs[12] = "青年湖"; vexs[13] = "信息工程学院"; vexs[14] = "体育馆"; vexs[15] = "丹桂苑"; vexs[16] = "南区大门"; CreateUDN(G); cout<<"分别输入起点和终点代号以空格分开"<>v0>>end; ShortPath(G,v0,P,D); cout<<"最短路径: "; for(i=0;i<G.vexnum;i++) { if(P[end-1][have[i]]==1) cout<<vexs [have[i]]<"; } cout<<endl<<"路径长度:"<<D[end-1]<<endl; cout<<"继续请按1,结束请按0;"<<endl; scanf("%d",&ctr); } }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值