แนวคิด
สำหรับตารางตัวเลขที่กำหนด ให้กำหนดความยาวสูงสุด ลำดับของงูและแสดงมัน สังเกตว่าหากมีลำดับงูหลายชุดที่มีความยาวสูงสุด ให้แสดงลำดับใดลำดับหนึ่ง
อันที่จริง ลำดับงูประกอบด้วยตัวเลขที่อยู่ติดกันในตาราง ดังนั้นสำหรับตัวเลขแต่ละตัว จากนั้นตัวเลขทางด้านขวาหรือตัวเลขด้านล่างจะเป็น +1 หรือ -1 ค่าของมัน ตัวอย่างเช่น หากเรากำหนดตำแหน่ง (a, b) ในตาราง เราสามารถย้ายไปทางขวาได้ เช่น (a, b+1) หากตัวเลขนั้นเป็น ± 1 หรือเลื่อนลง เช่น (a+1, b) หากตัวเลขนั้น คือ ± 1
ตัวอย่างเช่น
10, 7, 6, 3 9, 8, 7, 6 8, 4, 2, 7 2, 2, 2, 8
ในตารางด้านบน ลำดับงูสูงสุดคือ:(10, 9, 8, 7, 6, 7, 8)
รูปด้านล่างแสดงเส้นทางที่เป็นไปได้ทั้งหมด -
10 7 →6 3 ↓ ↓ ↓ 9 → 8 → 7→ 6 ↓↓ 8 4 2 7 ↓ 2 2 2 8
วิธีการ
ในที่นี้ แนวคิดคือการนำ Dynamic Programming ไปใช้ ในส่วนที่เกี่ยวกับแต่ละเซลล์ของเมทริกซ์ เราจะรักษาความยาวที่ยาวที่สุดของงูซึ่งสิ้นสุดในเซลล์ปัจจุบัน ตอนนี้ลำดับงูที่ยาวที่สุดจะมีค่าสูงสุด ที่นี่เซลล์ค่าที่ยาวที่สุดจะสอดคล้องกับหางของงู ในการพิมพ์งู เราต้องย้อนรอยจากหางไปจนถึงหัวงู สมมติว่า T[a][b] แทนความยาวสูงสุดของงูซึ่งสิ้นสุดที่เซลล์ (a, b) จากนั้นสำหรับเมทริกซ์ M ที่กำหนด ความสัมพันธ์ของ Dynamic Programming ถูกกำหนดเป็น -
T[0][0] = 0 T[a][b] = max(T[a][b], T[a][b – 1] + 1) if M[a][b] = M[a][b – 1] ± 1 T[a][b] = max(T[a][b], T[a – 1][b] + 1) if M[a][b] = M[a – 1][b] ± 1
ตัวอย่าง
// C++ program to find maximum length
// Snake sequence and print it
#include <bits/stdc++.h>
using namespace std;
#define M 4
#define N 4
struct Point{
int X, Y;
};
// Shows function to find maximum length Snake sequence path
// (a, b) corresponds to tail of the snake
list<Point> findPath(int grid1[M][N], int mat1[M][N],
int a, int b){
list<Point> path1;
Point pt1 = {a, b};
path1.push_front(pt1);
while (grid1[a][b] != 0){
if (a > 0 &&
grid1[a][b] - 1 == grid1[a - 1][b]){
pt1 = {a - 1, b};
path1.push_front(pt1);
a--;
}
else if (b > 0 &&
grid1[a][b] - 1 == grid1[a][b - 1]){
pt1 = {a, b - 1};
path1.push_front(pt1);
b--;
}
}
return path1;
}
// Shows function to find maximum length Snake sequence
void findSnakeSequence(int mat1[M][N]){
// Shows table to store results of subproblems
int lookup1[M][N];
// Used to initialize by 0
memset(lookup1, 0, sizeof lookup1);
// Used to store maximum length of Snake sequence
int max_len1 = 0;
// Used to store cordinates to snake's tail
int max_row1 = 0;
int max_col1 = 0;
// Used to fill the table in bottom-up fashion
for (int a = 0; a < M; a++){
for (int b = 0; b < N; b++){
// Perform except for (0, 0) cell
if (a || b){
// look above
if (a > 0 &&
abs(mat1[a - 1][b] - mat1[a][b]) == 1){
lookup1[a][b] = max(lookup1[a][b],
lookup1[a - 1][b] + 1);
if (max_len1 < lookup1[a][b]){
max_len1 = lookup1[a][b];
max_row1 = a, max_col1 = b;
}
}
// look left
if (b > 0 &&
abs(mat1[a][b - 1] - mat1[a][b]) == 1){
lookup1[a][b] = max(lookup1[a][b],
lookup1[a][b - 1] + 1);
if (max_len1 < lookup1[a][b]){
max_len1 = lookup1[a][b];
max_row1 = a, max_col1 = b;
}
}
}
}
}
cout << "Maximum length of Snake sequence is: "
<< max_len1 << endl;
// Determine maximum length Snake sequence path
list<Point> path1 = findPath(lookup1, mat1, max_row1,
max_col1);
cout << "Snake sequence is:";
for (auto it = path1.begin(); it != path1.end(); it++)
cout << endl << mat1[it->X][it->Y] << " ("<< it->X << ", " << it->Y << ")" ;}
// Driver code
int main(){
int mat1[M][N] ={{10, 7, 6, 3},{9, 8, 7, 6},{8, 4, 2, 7},{2, 2, 2, 8},};
findSnakeSequence(mat1);
return 0;
} ผลลัพธ์
Maximum length of Snake sequence is: 6 Snake sequence is: 10 (0, 0) 9 (1, 0) 8 (1, 1) 7 (1, 2) 6 (1, 3) 7 (2, 3) 8 (3, 3)