1. 程式人生 > 其它 >使用TensorFlow Object Detection Api 進行環境搭建、訓練自定義的資料集、輸出模型、Android端使用模型目標檢測

使用TensorFlow Object Detection Api 進行環境搭建、訓練自定義的資料集、輸出模型、Android端使用模型目標檢測

技術標籤:演算法學習記錄演算法

題目要求:
給定兩個序列X和Y,基於備忘錄方法,編寫程式找出X和Y所有的最長公共子序列

主要思路:
本題的主要思路是先輸入兩個公共序列,然後採用備忘錄方法來找出最長公共子序列的長度,根據最長公共子序列的長度來找出那些公共元素,把它們存到一個數組當中再輸出,這樣就可以解決問題了。
備忘錄方法,即採用自頂向下的遞迴來解決問題:從目標開始,將問題劃分,對子問題求解,直到邊界。第一步是先對備忘錄進行初始化,為了之後快速判斷是否有已經填寫過備忘錄。然後從兩個序列的最後一個數開始,如果這兩個數相等,就去查詢它們對應的備忘錄,如果大於-1說明已經計算過,就直接輸出結果,否則要查詢這兩個數的前一個數對應的備忘錄,因為這個備忘錄是由斜上方的備忘錄加一得到的,這樣一直查詢到邊界為止;如果這兩個最後的數不相等,那麼對應的備忘錄則是由它的左邊和上方的備忘錄求最大值得到的,需要對這兩個備忘錄進行查詢,如果都大於-1,說明已經計算過,就直接輸出結果,否則要遞迴呼叫函式進行計算。這樣就能得到兩個序列的最長公共子序列的長度了。

後面我們還要找出這些構成公共子序列的元素,我採用的是回溯法,從備忘錄的最後一位開始回溯,若當前位置數值與其左側位置數值相同時,說明從左側轉移到當前位置的LCS沒有延長,若當前位置數值與其上側位置數值相同時,說明從上側轉移到當前位置的LCS沒有延長,若當前位置數值與其上側、左側均不相同,說明此時LCS得到延長,應記錄當前位置所對應的字元。因為回溯法是逆序遍歷,所以我在用陣列存放這些字元時是逆序存入的,輸出陣列是正序輸出的。
在這裡插入圖片描述
該演算法的時間複雜度O(m * n),m,n為字串的長度。

#include <iostream>
#include <string>
#define
Max 50
using namespace std; //最長公共子字串,遞迴的備忘錄寫法 int cc[Max][Max]; int max(int x, int y) { if (x > y) { return x; } else { return y; } } int LCS_L(string s3,string s4,int len3,int len4, int cc[50][50]) { /* cout<<s3<<" "<<s4<<" "<<len3<<" "<<len4<<" "<<endl; for(int s=0;s<len3;s++) { for(int t=0;t<len4;t++) { cout<<cc[s][t]<<'\t'; } cout<<'\n'; }*/
if (cc[len3][len4]>-1) //如果cc[len3][len4]>-1,說明不是初值,已經計算過了,直接返回備忘錄裡面的值 { return cc[len3][len4]; } // 否則將數值存進備忘錄裡面 if (len3==0||len4==0) { cc[len3][len4]=0; } else if(s3[len3]==s4[len4])//如果s3[len3]==s4[len4],此時cc[len3][len4]=cc[len3-1][len4-1]+1 { if(cc[len3-1][len4-1]>-1)//此時cc[len3-1][len4-1]已經計算過了 cc[len3][len4]=cc[len3-1][len4-1]+1; else cc[len3][len4]=LCS_L(s3,s4,len3-1,len4-1,cc)+1;//否則要重新呼叫函式計算 } else //如果s3[len3]!=s4[len4],cc[len3][len4]=max(cc[len3-1][len4],cc[len3][len4-1]) { if(cc[len3-1][len4]>-1&&cc[len3][len4-1]>-1)//此時cc[len3-1][len4],cc[len3][len4-1]已經計算過了 cc[len3][len4]=max(cc[len3-1][len4],cc[len3][len4-1]); else cc[len3][len4]=max(LCS_L(s3,s4,len3-1,len4,cc),LCS_L(s3,s4,len3,len4-1,cc));//否則要重新呼叫函式計算 } return cc[len3][len4]; } void LCS_Print(string s3,int len3,int len4, int cc[50][50])//列印最長公共子序列 { int LCS_length=cc[len3][len4]; char lcs_print[50]=" ";//這個陣列儲存要列印的字串 while(LCS_length>0) { if(cc[len3][len4]!=cc[len3-1][len4-1]) { if(cc[len3-1][len4]==cc[len3][len4-1]) { lcs_print[LCS_length-1]=s3[len3-1];//這個數是從斜上方加1得到的 ,並且儲存的時候從後往前儲存 len3--;len4--; LCS_length--; } else if(cc[len3-1][len4]>cc[len3][len4-1]) len3--;//從左邊得到的數 else len4--;//從右邊得到的數 } else { len3--;len4--; } } cout<<"這個最長的公共子序列是:"; cout<<lcs_print<<" "<<endl; } void main() { string s3,s4; cout<<"請輸入兩個序列,以空格鍵隔開:"<<'\n'; cin>>s3>>s4; int len3 = s3.length(); int len4 = s4.length(); for(int i=1;i<=len3;i++)//將陣列cc初始化 { for(int j=1;j<=len4;j++) { cc[0][0]=0; cc[i][0]=0; cc[0][j]=0; cc[i][j]=-1; } } cout<<"兩個序列的公共最長子序列的長度為:"<<LCS_L(s3,s4,len3,len4,cc)<<'\n'; LCS_Print(s3,len3,len4,cc); }