最短路问题(动态规划解法)

题目描述

下图表示城市之间的交通路网,线段上的数字表示费用,单向通行由A->E。试用动态规划的最优化原理求出A->E的最省费用
 

输入

输入整数n表示有n个城市
然后是n行n列数据,第i行n个数据表示城市i到各个城市之间的距离,如果没有路径到达该城市,则数据为0

输出

输出最短路径值及经过的城市,格式见样例

样例输入 Copy

10
0  2  5  1  0  0  0  0  0  0
0  0  0  0 12 14  0  0  0  0
0  0  0  0  6 10  4  0  0  0
0  0  0  0 13 12 11  0  0  0
0  0  0  0  0  0  0  3  9  0
0  0  0  0  0  0  0  6  5  0
0  0  0  0  0  0  0  0 10  0
0  0  0  0  0  0  0  0  0  5
0  0  0  0  0  0  0  0  0  2
0  0  0  0  0  0  0  0  0  0

样例输出 Copy

minlong=19
1 3 5 8 10

AC代码:

#include<stdio.h>
#include<cstring>
#include<algorithm>
#include<iostream>
#define N 1050
using namespace std;
int n,m,k;
int dist[N];
int a[N][N];
int nex[N];
int dp(int u)//前面的点都遍历过后,可以得出前u各点每个点的最优值,最后考虑终点就能成立
{
	if(u>=n)//输入值错误直接返回
		return 0;
	if(dist[u]!=-1)
		return dist[u];//已经得出dist的话直接作为dp值返回 
	for(int i=1;i<=n;i++)
	{
		if(a[u][i] && (dist[u]==-1 || dist[u]>a[u][i]+dp(i)))//先要走一遍才可以考虑所有情况,所以这里用||   
		{
			dist[u]=a[u][i]+dp(i);
			nex[u]=i;//记录下一个走的是哪个点,dist反正是从小到大更新的,不用怕前边没有考虑到	
		}
	}
	return dist[u];
}
void dayin(int u)
{
	cout<<u<<" ";
	if(u==n)
		return;
	dayin(nex[u]); 
}
int main()
{
	cin>>n;
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=n;j++)
		{
			cin>>a[i][j];
		}
	}
	memset(dist,-1,sizeof dist);
	cout<<"minlong="<<dp(1)<<endl;
	dayin(1);
}

下面两段代码引自:Star77777的博客

正推dp: 

#include <iostream>
using namespace std;
 
const int maxn = 1e9;
int mp[10001][10001], dp[10001], p[10001];
 
void print(int k) {
	if (k == 0) return;
	print(p[k]);
	cout << k << " ";
}
 
int main()
{
	int n;
	cin >> n;
	for (int i = 1; i <= n; i++) {
		dp[i] = maxn;
		for (int j = 1; j <= n; j++) {
			cin >> mp[i][j];
		}
	}	
	dp[1] = 0;
	for (int i = 1; i <= n; i++) {
		for (int j = 1; j < i; j++) {
			if (mp[j][i] && dp[i] > dp[j] + mp[j][i] ) {
				dp[i] = dp[j] + mp[j][i];
				p[i] = j;
			}
		}
	}
	cout << "minlong=" << dp[n] << endl;
	print(n);
	return 0;
}

逆推dp:

#include <iostream>
using namespace std;
 
int mp[205][205], p[205], dp[205];
 
int main()
{
	int n, a[205], maxn = 0, k;
	cin >> n;
	for (int i = 1; i <= n; i++) {
		dp[i] = 100000000;
		for (int j = 1; j <= n; j++) {
			cin >> mp[i][j];
		}
	}
	dp[n] = 0;
	for (int i = n; i >= 1; i--) {
		for (int j = i + 1; j <= n; j++) {
			if (mp[i][j] && dp[i] > dp[j] + mp[i][j]) {
				dp[i] = dp[j] + mp[i][j];
				p[i] = j;
			}
		}
	}
	cout << "minlong=" << dp[1] << endl;
	k = 1;
	while (k) {
		cout << k << " ";
		k = p[k];
	}
	cout << endl;
	return 0;
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值