租用游艇问题(暴力法/动态规划)

租用游艇问题

问题描述:

长江游艇俱乐部在长江设置了n个游艇出租站1,2,…n,游客可在这些游艇出租站租用游艇,并在下游的任何一个游艇出租站归还游艇。游艇出租站i到游艇出租站j之间的租金为r(i,j) ,1<=i<j<=n,设计一个算法,计算出从出租站1到出租站n所需要的最少租金。


一、输入格式

第一行表示有n个站点,接下来n-1行是r( i , j)。

二、输出格式

输出最从游艇出租站1到出租站n所需的最少租金。

1.输入样例:

3
5 15
7

2.输出样例:

12

三、思路:

1.暴力算法:

很容易想到,我们可以用一个三重循环来遍历所有的选择,取最小的花费路线进行输出(num数组中读取输入的数据):

#include<bits/stdc++.h>
const int N = 1001;
using namespace std;

int n;
int num[N][N] = {
          
   0};

void readin(){
          
   
	for(int i = 1; i <= n - 1; i++){
          
   
		for (int j = i + 1; j <= n; j++)
			cin >> num[i][j];               
	}
}
int deal_one(){
          
   
	for(int r = 2 ; r <= n ; r++){
          
   
		for(int i = 1 ; i <= n - r + 1 ; i++){
          
   
			int j = i + r - 1;
			for(int k = i ; k <= j ; k++)
				num[i][j] = min(num[i][j] , num[i][k] + num[k][j]);
		}
	}
	return num[1][n];
} 

int main(){
          
   
	cout << "请输入出租站个数:
";
	cin >> n;
	readin();
	cout << "暴力:
"; 
	cout << deal_one();
}

2.动态规划:

1.我们容易发现,在上面的方法中,存在着很多可以优化的地方:比如说我们这道题目问的是从1 到 n 的最小花费,所以说我们可以设置一个dp数组,用dp[ i ]来表示从 1 到 i 的最优解。我们找到从 1 到 i 的最优解之后,我们要得到从 1 到 n 的最优解,只需要改变 i 的值来对比即可。显然我们用一个N的空间来换取了 n 3 n^3 n3 到 n 2 n^2 n2转变的时间复杂度。 2.状态的定义:

dp[ i ]表示从1 到 i 我们的最优选择;

3.状态转移方程:

dp[i] = min(dp[i] , dp[j] + dp[j] + num[j][i]);

代码如下:

#include<bits/stdc++.h>
const int N = 1001;
using namespace std;

int n;
int num[N][N] = {
          
   0};
int dp[N] = {
          
   0};

void readin(){
          
   
	for(int i = 1; i <= n - 1; i++){
          
   
		for (int j = i + 1; j <= n; j++) cin >> num[i][j];               
	}
}
int deal_two(){
          
   
	dp[1] = 0;
	dp[2] = num[1][2];
	
	for(int i = 3 ; i <= n ; i++){
          
   
		dp[i] = num[1][i];
		for(int j = 2 ; j <= n ; j++){
          
   
			dp[i] = min(dp[i] , dp[j] + num[j][i]);
		}
	}
	return dp[n];
}

int main(){
          
   
	cout << "请输入出租站个数:
";
	cin >> n;
	readin()
	cout << "暴力:
"; 
	cout << deal_one();
	cout << "
DP:
";
	cout << deal_two();
}
感谢阅读
经验分享 程序员 微信小程序 职场和发展