D
P
[
i
]
[
j
]
[
k
]
DP[i][j][k]
DP[i][j][k]:k表示(x+y)的值,即表示走的距离。i表示第一次走到x位置,j表示第二次走到j位置。
DP方程如code中
ACcode
#include<bits/stdc++.h>usingnamespace std;typedeflonglong ll;#definerep(i, a, n)for(int i = a; i <= n; i++)#defineper(i, a, n)for(int i = n; i >= a; i--)#definelowbit(x)((x)&-(x))#definelsonp <<1, l, mid#definersonp <<1|1, mid +1, r#definemem(a, b)memset(a, b,sizeof(a))#defineIOS\ios::sync_with_stdio(false);\cin.tie(0);\cout.tie(0)constdouble PI =acos(-1.0);const ll mod =1e9+7;
ll powmod(ll a, ll b){
ll res =1;
a %= mod;assert(b >=0);for(; b; b >>=1){if(b &1)
res = res * a % mod;
a = a * a % mod;}return res;}
ll gcd(ll a, ll b){return b ?gcd(b, a % b): a;}template<classT>inlinevoidread(T &res){char c;
T flag =1;while((c =getchar())<'0'|| c >'9')if(c =='-')
flag =-1;
res = c -'0';while((c =getchar())>='0'&& c <='9')
res = res *10+ c -'0';
res *= flag;}int dp[15][15][36];int a[17][17];intmain(){
IOS;int n;
cin >> n;int x, y, z;while(cin >> x >> y >> z){if(x == y && y == z && z ==0)break;
a[x][y]= z;}for(int k =2; k <= n + n; k++){for(int i1 =1; i1 <= n; i1++){for(int i2 =1; i2 <= n; i2++){int j1 = k - i1, j2 = k - i2;if(j1 >=1&& j1 <= n && j2 >=1&& j2 <= n){int w = a[i1][j1];if(i1 != i2)
w += a[i2][j2];
dp[i1][i2][k]=max(dp[i1][i2][k], dp[i1 -1][i2 -1][k -1]+ w);//下下
dp[i1][i2][k]=max(dp[i1][i2][k], dp[i1][i2 -1][k -1]+ w);//右下
dp[i1][i2][k]=max(dp[i1][i2][k], dp[i1 -1][i2][k -1]+ w);//下右
dp[i1][i2][k]=max(dp[i1][i2][k], dp[i1][i2][k -1]+ w);//右右}}}}
cout << dp[n][n][2* n];return0;}
二、最长上升子序列
1、基础的最长上升子序列O(n^2)
for(int i =1; i <= n ; i++){
dp[i]=1;int maxx =0;for(int j =1; j < i ; j++){if(a[i]> a[j]) maxx =max(maxx,dp[j]);}
dp[i]+= dp[j];}
#include<bits/stdc++.h>usingnamespace std;typedeflonglong ll;#definerep(i, a, n)for(int i = a; i <= n; i++)#defineper(i, a, n)for(int i = n; i >= a; i--)#definelowbit(x)((x)&-(x))#definelsonp <<1, l, mid#definersonp <<1|1, mid +1, r#definemem(a, b)memset(a, b,sizeof(a))#defineIOS\ios::sync_with_stdio(false);\cin.tie(0);\cout.tie(0)constdouble PI =acos(-1.0);const ll mod =1e9+7;
ll powmod(ll a, ll b){
ll res =1;
a %= mod;assert(b >=0);for(; b; b >>=1){if(b &1)
res = res * a % mod;
a = a * a % mod;}return res;}
ll gcd(ll a, ll b){return b ?gcd(b, a % b): a;}template<classT>inlinevoidread(T &res){char c;
T flag =1;while((c =getchar())<'0'|| c >'9')if(c =='-')
flag =-1;
res = c -'0';while((c =getchar())>='0'&& c <='9')
res = res *10+ c -'0';
res *= flag;}constint N =1003;int a[N];int dp[N];int ans1, ans2;int n;int g[N];intmain(){
IOS;int x;while(cin >> x)
a[++n]= x;for(int i =1; i <= n; i++){
dp[i]=1;int maxx =0;for(int j =1; j < n; j++){if(a[i]<= a[j])
maxx =max(dp[j], maxx);}
dp[i]+= maxx;
ans1 =max(ans1, maxx);}int cnt =0;for(int i =1; i <= n; i++){int idx =0;while(idx < cnt && g[idx]< a[i])//找到第一个小于g的数
idx++;
g[idx]= a[i];if(idx >= cnt)
cnt++;}
cout << ans1 <<"\n"<< cnt;return0;}
d
p
[
i
]
[
j
]
dp[i][j]
dp[i][j]:a中前i个数字,b中前j个数字,且以b[j]为结尾的子序列长度最大
状态转移:
不选择a[i],
d
p
[
i
]
[
j
]
=
m
a
x
(
d
p
[
i
]
[
j
]
,
d
p
[
i
−
1
]
[
j
]
)
dp[i][j] = max(dp[i][j],dp[i-1][j])
dp[i][j]=max(dp[i][j],dp[i−1][j])
选择a[i],且
a
i
=
b
j
,
b
j
>
b
k
,
d
p
[
i
]
[
j
]
=
m
a
x
(
d
p
[
i
]
[
j
]
,
d
p
[
i
−
1
]
[
k
]
+
1
)
a_i=b_j,b_j>b_k,dp[i][j] = max(dp[i][j],dp[i-1][k]+1)
ai=bj,bj>bk,dp[i][j]=max(dp[i][j],dp[i−1][k]+1)
状态优化:
对于第二种,状态,每次都是使用i-1的状态转移,可以存储
d
p
[
i
−
1
]
[
j
]
+
1
dp[i-1][j]+1
dp[i−1][j]+1的最大值。
ACcode
#include<bits/stdc++.h>usingnamespace std;typedeflonglong ll;#definerep(i, a, n)for(int i = a; i <= n; i++)#defineper(i, a, n)for(int i = n; i >= a; i--)#definelowbit(x)((x)&-(x))#definelsonp <<1, l, mid#definersonp <<1|1, mid +1, r#definemem(a, b)memset(a, b,sizeof(a))#defineIOS\ios::sync_with_stdio(false);\cin.tie(0);\cout.tie(0)constdouble PI =acos(-1.0);const ll mod =1e9+7;
ll powmod(ll a, ll b){
ll res =1;
a %= mod;assert(b >=0);for(; b; b >>=1){if(b &1)
res = res * a % mod;
a = a * a % mod;}return res;}
ll gcd(ll a, ll b){return b ?gcd(b, a % b): a;}template<classT>inlinevoidread(T &res){char c;
T flag =1;while((c =getchar())<'0'|| c >'9')if(c =='-')
flag =-1;
res = c -'0';while((c =getchar())>='0'&& c <='9')
res = res *10+ c -'0';
res *= flag;}constint N =3005;int dp[N][N];//前i和j个字母,以b[j]结尾的LICSint a[N], b[N];intmain(){
IOS;int n;
cin >> n;rep(i,1, n) cin >> a[i];rep(j,1, n) cin >> b[j];for(int i =1; i <= n; i++)//a[i]{int maxx =1;for(int j =1; j <= n; j++)//b[j]{
dp[i][j]= dp[i -1][j];//不选取a[i]if(a[i]== b[j])//选a[i]{
dp[i][j]=max(dp[i][j], maxx);}if(b[j]< a[i])
maxx =max(maxx, dp[i][j]+1);}}int ans =0;rep(i,1, n)
ans =max(ans, dp[n][i]);
cout << ans;return0;}