動態規劃入門篇

求求求亮發表於2020-10-16

本文根據B站UP主視訊總結,有需要的朋友看看到原連結看看。
參考連結: https://www.bilibili.com/video/BV12W411v7rd?from=search&seid=775970335865336023

一、求陣列中不相連的數之和最大

直接上題, 在陣列中arr[1, 2, 4, 1, 7, 8, 3] 中求不相連的數之和的最大值。

1、 實現思路

首先,求不相連的數之和, 那麼就存在一個問題, 選或者不選。如果選了ar一個數那就不能選他隔壁的數, 只能選與他相隔1的。 我們可以從最後一個數來考慮, 再遞推回去。
如下圖所示, 我們建立一個函式OPT(), 表示當前的最佳狀態(即最大值), OPT(6)即表示7個數(arr[0]~arr[6])都考慮時的最大值, 如果7個數都考慮, 那麼我們就要考慮一個問題, 第七個數 arr[6] 選不選, 所以會有兩種情況, 選arr[6] 或者不選 arr[6]。
在這裡插入圖片描述

  • 選arr[6], 那麼arr[5]與arr[6]相鄰肯定不能選,所以只能考慮arr[0]~arr[4]的最佳組合, 即opt(4), 所以此時最佳狀態為 OPT(4)+arr[6].
  • 不選arr[6], 那麼arr[5]就可以選擇了, 所以此時的最佳狀態應該是OPT[5]。

然後再以遞迴的思路遞推至OPT(1), OPT(0)。

2、改進

使用遞迴能夠完成題目要求, 但是使用遞迴的過程中做了很多重複的工作,這樣會使時間複雜度大大提高,我們應該避免這種情況的出現。所以我們使用一個陣列opt[i] 將每次得到的OPT(i)存放起來。
在這裡插入圖片描述

3、原始碼

#include <iostream>
#include <vector>

using namespace std;

/******************************************************************
*	函式功能: 使用遞迴,返回陣列中互不相連的數的最大和
*	傳入引數: vector陣列地址(陣列名), 陣列大小 
******************************************************************/
int rec_opt(vector<int>*arr, int size)
{
	int rv =0 ;
	if(size == 1)  //陣列中只有一個數,此時的最佳即為這個數。
	{
		rv = arr->at(0);
		return rv;
	}
	else if(size == 2) //陣列中有兩個數時,判斷兩數大小,來決定最佳數。
	{
		if(arr->at(1)>arr->at(0))
		{
			rv = arr->at(1);
		}
		else 
		{
			rv = arr->at(0);
		}
		return rv;
	}
	else
	{
		int temp_1=0, temp_2=0;
		
		temp_1 = rec_opt(arr, size-1); //不選
		temp_2 = rec_opt(arr,size-2)+arr->at(size-1); //選
		if(temp_1>temp_2)
		{
			return temp_1;
		}
		else 
		{
			return temp_2;	
		}
	}	
}

/***********************************************************************
*	函式功能: 使用動態規劃思想, 返回陣列中不相連的數之和的最大值
*	傳入引數: vector陣列地址(陣列名) 
***********************************************************************/ 

int dp_opt(vector<int> *arr)
{
	vector<int>opt;
	cout<<arr->at(0)<<endl;
	opt.push_back(arr->at(0));

	opt.push_back(max(arr->at(0), arr->at(1)));
	
	for(int i=2; i<arr->size(); i++)
	{
		int temp_1=0, temp_2=0;
		temp_1 = opt.at(i-2)+arr->at(i);
		temp_2 = opt.at(i-1);
		opt.push_back(max(temp_1, temp_2));
		
	}
	
	return opt.at(arr->size()-1);
}
int main()
{
	vector<int> arr;
	int num=0;
	cout<<"請輸入陣列大小"<<endl;
	cin>>num;
	for(int i=0; i<num; i++)
	{
		int temp=0;
		cin>>temp;
		arr.push_back(temp);
		 
	}
	 
	cout<<"兩數之和最大值為:"<<rec_opt(&arr, arr.size())<<endl;
	cout<<"use dp..."<<endl;
	cout<<"兩數之和最大值為:"<<dp_opt(&arr)<<endl;	
	return 0;
 } 

相關文章