參考:
定義狀態
dp[i][j] 表示序列 a 與序列 b 的以 b[j] 結尾的 lcis 的長度
狀態轉移方程
①、若 a[i] != b[j],dp[i][j] = dp[i-1][j]
②、若 a[i] == b[j],dp[i][j] = max(dp[i-1][k]) + 1 (1 <= k < j && b[k] < b[j])
對於①:
dp[i][j] 是以 b[j] 為結尾的且 a[i] != b[j],所以 a[i] 對 dp[i][j] 沒有貢獻,必然有 dp[i][j] = dp[i-1][j]
對於②:
已知 a[i] == b[j],我們只要在前面找到乙個最長的且結尾小於 b[j] 的 lcis,然後將 b[j] 接到其後面就可以得到乙個以 b[j] 結尾的 lcis
時間複雜度的優化
可以發現,當 a[i] == b[j] 時,我們需要找到乙個 dp[i-1][k] 來取得最優解,且 b[k] < b[j],那麼必然有b[k] < a[i]
所以我們可以維護乙個 max 來儲存 dp[i-1][k] 的值,只要有 a[i] > b[j] 的地方就去嘗試更新這個最大值
也可以維護乙個 t 來儲存 k 的值
空間複雜度的優化
因為每次只需要用到 dp[i-1][j],所以可以優化到一維空間
hdu 1423 greatest common increasing subsequence
瞎搞了乙個 n ^ 4 解法竟然也可以過...資料貌似有點水
#include #include #include #include #include #include #include #include #include #include #include using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef unsigned int uint;
const ull mod = 1e9 + 7;
const ll inf = 0x7ffffffff;
const int maxn = 500 + 10;
ll a1[maxn], a2[maxn];
ll dp[maxn][maxn];
ll b[maxn];
int main()
scanf("%d", &m2);
for (int i = 1; i <= m2; ++i)
a1[0] = a2[0] = -inf;
memset(dp, 0, sizeof(dp));
int max = 0;
for (int i = 1; i <= m1; ++i) }}
if (dp[i][j] > max) }}
}printf("%d\n", max);
if (t != 0)
}return 0;
}
#include #include #include #include #include #include #include #include #include #include #include using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef unsigned int uint;
const ull mod = 1e9 + 7;
const int inf = 0x7fffffff;
const int maxn = 500 + 10;
int a1[maxn], a2[maxn];
int dp[maxn];
int main()
scanf("%d", &m2);
for (int i = 1; i <= m2; ++i)
memset(dp, 0, sizeof(dp));
for (int i = 1; i<= m1; ++i) else if (a1[i] > a2[j] && dp[t] < dp[j]) }}
int ans = 0;
for (int i = 1; i <= m2; ++i)
}printf("%d\n", ans);
if (t != 0)
}return 0;
}
poj 2127 greatest common increasing subsequence
解題思路:
如果題目要求列印路徑,應該用二維來做
因為一維存路徑的話,在乙個已經滿足上公升的序列中,可能會有後面的替換之前的前驅
63 6 9 12 4 6
53 4 6 9 12
比如這個序列,i = 3 6 9 12 的時候 dp = 1 0 2 3 4
4 到來的時候使之成為 1 2 2 3 4
這時候 6 再來,則改變了 6 原本位置上的前驅
這個 dp 的定義,可能會改變前驅,因為 dp[j] 只是以 j 為結尾而並沒有限制條件
#include #include #include #include #include #include #include #include #include #include #include using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef unsigned int uint;
const ull mod = 1e9 + 7;
const int inf = 0x7fffffff;
const int maxn = 500 + 10;
int a1[maxn], a2[maxn];
int dp[maxn][maxn];
int pre[maxn][maxn];
int main()
scanf("%d", &m2);
for (int i = 1; i <= m2; ++i)
memset(pre, 0, sizeof(pre));
memset(dp, 0, sizeof(dp));
int max = 0;
int pos1 = 0, pos2 = 0;
for (int i = 1; i<= m1; ++i) else if (a1[i] > a2[j] && dp[i-1][t] < dp[i-1][j])
if (dp[i][j] > max) }}
printf("%d\n", max);
stackstack;
while (max != 0)
--pos1;
}if (!stack.empty())
while (!stack.empty())
printf("\n");
}return 0;
}
LCIS 最長公共上公升子串行
1004 tyvj1071 lcis最長公共上公升子串行 description 熊大媽的奶牛在小沐沐的薰陶下開始研究資訊題目。小沐沐先讓奶牛研究了最長上公升子串行,再讓他們研究了最長公共子串行,現在又讓他們要研究最長公共上公升子串行了。小沐沐說,對於兩個串a,b,如果它們都包含一段位置不一定連續的...
LCIS (最長公共上公升子串行)
ac通道 題目含義就是求最長公共上公升子串行 首先考慮,最長公共上公升子串行 最長上公升子串行 最長公共子串行,可以通過lis和lcs的思想去考慮本題目。定義狀態 dp i j 表示a陣列的前i個和b陣列的前j個且以b j 結尾的lcis長度考慮狀態轉移 轉移有兩種情況 a i b j 時候的轉移,...
最長公共上公升子串行(LCIS)
題解熊大媽的奶牛在小沐沐的薰陶下開始研究資訊題目。小沐沐先讓奶牛研究了最長上公升子串行,再讓他們研究了最長公共子串行,現在又讓他們研究最長公共上公升子串行了。小沐沐說,對於兩個數列a和b,如果它們都包含一段位置不一定連續的數,且數值是嚴格遞增的,那麼稱這一段數是兩個數列的公共上公升子串行,而所有的公...