1. 程式人生 > >[洛谷]P1359 租用遊艇 (#動態規劃 -1.5)(#圖論 -1.5)

[洛谷]P1359 租用遊艇 (#動態規劃 -1.5)(#圖論 -1.5)

題目描述

長江遊艇俱樂部在長江上設定了n 個遊艇出租站1,2,…,n。遊客可在這些遊艇出租站租用遊艇,並在下游的任何一個遊艇出租站歸還遊艇。遊艇出租站i 到遊艇出租站j 之間的租金為r(i,j),1<=i<=j<=n。試設計一個演算法,計算出從遊艇出租站1 到遊艇出租站n 所需的最少租金。

對於給定的遊艇出租站i 到遊艇出租站j 之間的租金為r(i,j),1<=i<j<=n,程式設計計算從遊艇出租站1 到遊艇出租站n所需的最少租金。

保證計算過程中任何時刻數值都不超過10^6

輸入輸出格式

輸入格式:

由檔案提供輸入資料。檔案的第1 行中有1 個正整數n(n<=200),表示有n個遊艇出租站。接下來的n-1 行是一個半矩陣r(i,j),1<=i<j<=n。

輸出格式:

程式執行結束時,將計算出的從遊艇出租站1 到遊艇出租站n所需的最少租金輸出到檔案中。

輸入輸出樣例

輸入樣例#1

3
5 15
7

輸出樣例#1

12

思路

首先想到的應該是圖論的做法,又n<=200,果斷可以用Floyd。但是可以用dp做。如果你沒看懂題意和樣例,下面這張圖會幫助你理解。

#include <stdio.h>
#include <iostream>
using namespace std;
int dp[201],n;//dp[i]表示到這個點(點now)的最短路徑,其實這題可以套Floyd的模版,但是dp做會很方便,個人覺得dp難理解,圖論做就複雜了
int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0);
	int i,j;
	cin>>n;
	for(i=1;i<n;i++)
	{
		for(j=i+1;j<=n;j++)
		{
			int now;
			cin>>now;
			if(dp[j]==0)//如果沒到過
			{
				dp[j]=now;
			}
			else
			{
				dp[j]=min(dp[j],dp[i]+now);
			}//從1裡原有的路徑和從2到3的路徑比較那個短
		}
	}
	//for(i=1;i<=n;i++)
	//{
	//	cout<<dp[i]<<' ';
	//}
	cout<<dp[n]<<endl;
	cout<<endl;
	return 0;
}

當然,題目中也提到了“最短路”的字眼。再看看資料,哇,n<=200,那就Floyd吧。

#include <stdio.h>
#include <iostream>
using namespace std;
int n,a[201][201]; 
int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0);
	int i,j,k;
	cin>>n;
	for(i=1;i<=n;i++)
	{
		for(j=1;j<=n;j++)
		{
			if(i!=j)
			{
				a[i][j]=1<<30;//圖論中的初始化,不理解的出門右轉到圖的遍歷那一節瞭解一下(逃) 
			}
		}
	}
	for(i=1;i<=n;i++)
	{
		for(j=i+1;j<=n;j++)
		{
			cin>>a[i][j];//輸入 
		}
	}
	for(i=1;i<=n;i++)
	{
		for(j=1;j<=n;j++)
		{
			for(k=1;k<=n;k++)//Floyd最短路 
			{
				a[j][k]=min(a[j][k],a[j][i]+a[i][k]);//直接套Floyd模版
			}//打算在我的演算法報刊第12期寫個關於最短路的演算法 
		}
	}
	cout<<a[1][n]<<endl;
	return 0;
}