a.
b.
1.對(中問題6:最長遞增子串行的改進,減少時間複雜度
演算法的思想:
它不是使用的動態規劃法,而是普通的演算法思想,就是在陣列中直接儲存最長遞增子串行,在迴圈的過程中不斷的查詢插入位置,直到最終找到。下面列出實現的過程:
從上面的過程可以看出該演算法的實現過程,在查詢sub合適插入位置的時候,使用了二分查詢,提高了查詢速度,這個演算法本身也比前面利用動態規劃法簡單,但是該演算法複雜之處不在演算法
而在演算法正確性的證明!,演算法證明見:
**:
#include #include using namespace std;
const int min = -32768;
/** *a :原始陣列
*sub :最終獲取的最大遞增子串行(注意,sub[0]是哨兵,結果從1開始)
*length :陣列長度
**/int longestsub(int* a, int* sub, int length)
return len;
}int main();
int* sub = new int[13];
memset(sub,0,sizeof(int));
int length = longestsub(a,sub,13);
cout<
不過其結果和改進之前的有些不同,前面是,改進之後是結果都是正確的!
2.實際應用的兩個例子
a.造橋問題
問題描述:
要在一條河的南北兩邊的各個城市之間造若干座橋.橋兩邊的城市分別是a(1)...a(n)和b(1)...b(n).這裡的要求a(i)只可以和b(i)之間造橋,同時兩座橋之間不能交叉.希望可以得到乙個盡量多座橋的方案.
問題分析:
首先,這是乙個動態規劃的問題,即解答有許多中,尋找乙個最優的解決方案。
其次,問題抽象,就是怎樣將這個問題抽象成乙個數學模型進行解決
第一步:就是搞清楚問題是什麼?-------就是對號入座a對應於b的序號,這樣的解決方案有許多如1,5,4和2,5,4以及1,3
第二步:抽象-------抽象成兩個陣列s1(1,2,5,4,3), s2(2,1,3,5,4),然後找s1和s2中相同的數字,且序號必須在陣列下標遞增,找出最多的對數
(即s1中的1對應了s2中的1,s1中的2對應了s2中的2,雖然s1中的下標是1,2 但是在s2中的下標是2,1沒有遞增,故而是不行的---更簡單的說就是上面圖不能交叉)
第三步:找規律--------這是最難的,如何才能從中找到突破口,我們在尋找的過程中發現,聯絡s1和s2的橋梁是什麼?就是組成對的兩個數在各自陣列中的下標
那我們把這些下標都寫出來,只是寫一方就可以了從s1到s2的,就設為s3(2,1,4,5,3)---就表示s3[0]=2表示s1陣列第乙個值對應與s2中的第二個值(這個2就是在s2中的下標),
從而依次就把s3寫出來了,這樣找對數最多,而s3表示的是連線時對方的下標,那麼是不是只要下標遞增就不會交叉了?事實就是這樣!!
就是找s3中的最長遞增陣列,這裡就是或者
第四步:寫**-------既然突破口找到了,**就不是問題了
**/**
*建橋問題
**/#include #include using namespace std;
/** *建立建橋索引陣列
*a : 原始陣列a
*b : 原始陣列b
*c :建立的索引陣列
*length :陣列長度
*/void build(const int* a, const int* b, int* c, int length)
} }int m=0,k=0;
for (int i=1;i<=n;i++)
delete t;
delete p;
p = null;
t = null;
}int main();
int b = ;
int length = sizeof(a)/sizeof(int);
//索引陣列
int* c = new int[length];
//儲存最終結果
int* sub = new int[length];
memset(sub,0,sizeof(int));//初始化sub
memset(sub,0,sizeof(int));//初始化sub
build(a,b,c,length);
longestincreasesub(c,length, sub);
printresult(b,sub, length);
delete c;
delete sub;
c = null;
sub = null;
return 0;
}
b.疊箱子問題問題描述:
1.一排有許多不同的箱子,長寬高不一樣
2.你需要把他疊放的盡量的高.但是箱子的擺放必須滿足大的在下面,小的在上面的原則
3.箱子可以任意旋轉(這就意味著你要用乙個箱子的時候,旋轉到合適位置)
問題分析:
具體分析見圖:
注1:盒子要比上面的大--準確的說,是wi>wj && di>dj,單獨使用si>sj不準確,因為可能很長但很窄,不和題目要求
為了滿足要求,我們人為規定,w<=d(輸入時確定或者後來處理),這樣就不用擔心這個問題了,使用si>sj就滿足要求。
注2:記住盒子可以旋轉,意味著每個盒子可以有三個面可以使用,旋轉數量不限。
注3:本體關鍵是建立模型,列出動態規劃的方程
**:
/**
* *疊箱子問題
*/#include #include #include #include using namespace std;
//定義乙個箱子結構體
struct box;
//排序比較器
bool boxcompare(const box& a, const box&b)
//最高的堆疊高度演算法
int highestbox(const vector& b)
最長遞增子串行
這是微軟實習生筆試遇到的,題意 求乙個陣列中最長遞增子串行的長度。要求選擇該題最好演算法的時間複雜度和空間複雜度。答案 時間複雜度o nlgn 空間複雜度o n 這題明顯用動態規劃來解。假設在目標陣列array 的前i個元素中,以array i 元素為最大元素的遞增子串行的長度是lis i 那麼 遞...
最長遞增子串行
最長遞增子串行又叫做最長上公升子串行 子串行,正如lcs一樣,元素不一定要求連續。本節討論實現三種常見方法,主要是練手。題 求乙個一維陣列arr i 中的最長遞增子串行的長度,如在序列1,1,2,3,4,5,6,7中,最長遞增子串行長度為4,可以是1,2,4,6,也可以是 1,2,4,6。方法一 d...
最長遞增子串行
最長遞增子串行 求乙個字串的最長遞增子串行 如 dabdbf最長遞增子串行就是abdf,長度為4 這是一道基本的動態規劃求解的題目,與此類似的還有 最長公共子串行 分析 用一維陣列dp i 來儲存以a i 為末元素的最長遞增子串行的長度,那麼dp i 至少為1 即包含它本身 往前尋找,如果存在a j...