สมมติว่าเราเขียนจำนวนเต็มของ A และ B (ตามลำดับที่กำหนด) ในเส้นแนวนอนสองเส้นแยกกัน ตอนนี้ เราอาจวาดเส้นเชื่อม:เส้นตรงที่เชื่อมตัวเลขสองตัว A[i] และ B[j] ในลักษณะที่ว่า −
-
A[i] ==B[j];
-
เส้นที่เราวาดซึ่งไม่ตัดกับเส้นเชื่อมต่ออื่น (ไม่ใช่แนวนอน)
เราต้องจำไว้ว่าเส้นเชื่อมต่อไม่สามารถตัดกันได้แม้ที่จุดปลาย - แต่ละหมายเลขสามารถอยู่ในสายเชื่อมต่อเดียวเท่านั้น ค้นหาจำนวนสายเชื่อมต่อสูงสุด ดังนั้นหากอินพุตเป็น [1,4,2] และ [1,2,4] ผลลัพธ์จะเป็น 2
1 | 4 | 2 |
1 | 2 | 4 |
เราสามารถวาดเส้นที่ไม่ขีดเส้น 2 เส้นดังในแผนภาพ เราไม่สามารถลากเส้นที่ไม่ผ่าน 3 เส้นได้ เนื่องจากเส้นจาก A[1]=4 ถึง B[2]=4 จะตัดกับเส้นจาก A[2]=2 ถึง B[1]=2
เพื่อแก้ปัญหานี้ เราจะทำตามขั้นตอนเหล่านี้ -
-
กำหนดวิธีการที่เรียกว่าแก้ปัญหา () ซึ่งจะใช้เวลา i, j, อาร์เรย์ A, อาร์เรย์ B และเมทริกซ์ dp
-
ถ้าฉันอยู่นอกช่วงอาร์เรย์ A ให้คืนค่า 0
-
ถ้า j อยู่นอกช่วงอาร์เรย์ B ให้คืนค่า 0
-
nj :=เจ
-
ในขณะที่ nj <ขนาดของ B และ B[nj] ไม่ใช่ A[i]
-
เพิ่ม nj ขึ้น 1
-
-
temp :=1 เมื่อ nj <ขนาดของ B มิฉะนั้น 0
-
ret :=สูงสุดของ (แก้ (i + 1, j, A, B, dp) และอุณหภูมิ) + แก้ปัญหา (i + 1, nj + 1, A, B, dp)
-
dp[i, j] :=ret และ return ret
-
จากวิธีหลัก
-
n :=ขนาดของ A, m :=ขนาดของ B
-
สร้างเมทริกซ์ขนาด dp n x m และเติมด้วย – 1
-
โทรแก้(0, 0, A, , dp)
ให้เราดูการใช้งานต่อไปนี้เพื่อความเข้าใจที่ดีขึ้น -
ตัวอย่าง
#include <bits/stdc++.h> using namespace std; class Solution { public: int solve(int i, int j, vector <int>&A, vector <int>&B, vector < vector <int> >& dp){ if(i >= A.size()) return 0; if(j >= B.size()) return 0; if(dp[i][j] != -1) return dp[i][j]; int nj = j; while(nj < B.size() && B[nj] != A[i]) nj++; int ret = max(solve(i + 1, j, A, B, dp), (nj < B.size() ? 1 : 0) + solve(i + 1, nj + 1, A, B, dp)); return dp[i][j] = ret; } int maxUncrossedLines(vector<int>& A, vector<int>& B) { int n = A.size(); int m = B.size(); vector < vector <int > > dp(n, vector <int>(m, -1)); return solve(0, 0, A, B, dp); } }; main(){ vector<int> v1 = {1,4,2}; vector<int> v2 = {1,2,4}; Solution ob; cout << (ob.maxUncrossedLines(v1, v2)); }
อินพุต
[1,4,2] [1,2,4]
ผลลัพธ์
2