状态转移顺推以及逆推均可,以逆推为例,
d
p
[
i
]
[
j
]
[
k
]
=
m
a
x
(
d
p
2
[
i
]
[
j
]
[
k
]
,
d
p
[
i
−
1
]
[
j
−
v
a
l
[
w
]
[
k
]
]
[
w
]
+
(
k
=
=
1
?
a
[
i
]
[
1
]
:
0
)
)
;
dp[i][j][k] = max( dp2[i][j][k] , dp[i - 1][j - val[w][k]][w] + ( k == 1 ? a[i][1] : 0 )) ;
dp[i][j][k]=max(dp2[i][j][k],dp[i−1][j−val[w][k]][w]+(k==1?a[i][1]:0));按照这个方程算一遍即可,主要注意最好开数组val来保存从状态x转化到状态y所至少需要多多少子矩阵
顺推就是用当前状态更新未知状态,转移方程是
d
p
[
i
+
1
]
[
j
+
v
a
l
2
[
k
]
[
w
]
]
[
w
]
=
m
a
x
(
d
p
[
i
+
1
]
[
j
+
v
a
l
[
k
]
[
w
]
]
[
w
]
,
d
p
[
i
]
[
j
]
[
k
]
)
+
c
a
l
(
i
,
w
)
dp[i + 1][j + val2[k][w]][w] = max( dp[i + 1][j + val[k][w]][w] , dp[i][j][k] ) + cal(i , w)
dp[i+1][j+val2[k][w]][w]=max(dp[i+1][j+val[k][w]][w],dp[i][j][k])+cal(i,w),几乎同逆推
当m = 2时,只要改一下val[w][k]的值以及后面的式子即可
代码
//顺推# include<iostream># include<cstdio>usingnamespace std ;constint NR =105;int n , m , t ;int dp1[NR][20][2];int dp2[NR][15][5];int a[NR][3];int val1[2][2]={{0,1},{0,0}};int val2[5][5]={{0,1,1,1,2},{0,0,1,1,1},{0,1,0,1,1},{0,1,1,0,2},{0,0,0,1,0}};voiddo1(){for(int i =0; i < NR ; i++)for(int j =0; j <=15; j++)for(int k =0; k <=1; k++)
dp1[i][j][k]=-1e9;for(int j =0; j <=15; j++)
dp1[0][j][0]=0;for(int i =0; i < n ; i++)for(int j =0; j <= t ; j++){for(int k =0; k <=1; k++){if( k ==1)
dp1[i][j][k]+= a[i][1];for(int w =0; w <=1; w++){if( j + val1[k][w]> t )continue;
dp1[i +1][j + val1[k][w]][w]=max(
dp1[i +1][j + val1[k][w]][w], dp1[i][j][k]);}}}int ans =-1e9;for(int i =0; i <=1; i++){if( i ==1)
dp1[n][t][i]+= a[n][1];
ans =max( ans , dp1[n][t][i]);}printf("%d\n", ans);}voiddo2(){for(int i =0; i < NR ; i++)for(int j =0; j <=15; j++)for(int k =0; k <=4; k++)
dp2[i][j][k]=-1e9;for(int j =0; j <=15; j++)
dp2[0][j][0]=0;for(int i =0; i < n ; i++)for(int j =0; j <= t ; j++){for(int k =0; k <=4; k++){if( k ==1)
dp2[i][j][k]+= a[i][1];if( k ==2)
dp2[i][j][k]+= a[i][2];if( k ==3|| k ==4)
dp2[i][j][k]+= a[i][1]+ a[i][2];for(int w =0; w <=4; w++){if( j + val2[k][w]> t )continue;
dp2[i +1][j + val2[k][w]][w]=max(
dp2[i +1][j + val2[k][w]][w], dp2[i][j][k]);}}}int ans =-1e9;for(int i =0; i <=4; i++){if( i ==1)
dp2[n][t][i]+= a[n][1];if( i ==2)
dp2[n][t][i]+= a[n][2];if( i ==3|| i ==4)
dp2[n][t][i]+= a[n][1]+ a[n][2];
ans =max( ans , dp2[n][t][i]);}printf("%d\n", ans);}intmain(){scanf("%d%d%d",&n ,&m ,&t );for(int i =1; i <= n ; i++){for(int j =1; j <= m ; j++){scanf("%d",&a[i][j]);}}if( m ==1){do1();}else{do2();}return0;}
//逆推# include<iostream># include<cstdio># include<algorithm>usingnamespace std ;constint NR =105;int n , m , t ;int dp1[NR][15][2];int dp2[NR][15][5];int a[NR][3];int val2[5][5]={{0,1,1,1,2},{0,0,1,1,1},{0,1,0,1,1},{0,1,1,0,2},{0,0,0,1,0}};voiddo1(){for(int j =0; j <15; j++)
dp1[0][j][1]=-1e9;for(int j =0; j <15; j++)
dp1[0][j][0]=0;for(int i =1; i <= n ; i++)for(int j =0; j <= t ; j++)for(int k =0; k <=1; k++){
dp1[i][j][k]=-1e9;if( j - k >=0)
dp1[i][j][k]= dp1[i -1][j - k][0];
dp1[i][j][k]=max( dp1[i][j][k], dp1[i -1][j][1]);if( k )
dp1[i][j][k]+= a[i][1];}printf("%d\n",max( dp1[n][t][0], dp1[n][t][1]));}intcalc(int p ,int q ){int ans =0;if( q ==1|| q ==3|| q ==4)
ans += a[p][1];if( q ==2|| q ==3|| q ==4)
ans += a[p][2];return ans ;}voiddo2(){for(int i =0; i <= n ; i++)for(int j =0; j <= t ; j++)for(int k =0; k <=4; k++)
dp2[i][j][k]=-1e9;for(int j =0; j <15; j++)
dp2[0][j][0]=0;for(int i =1; i <= n ; i++)for(int j =0; j <= t ; j++){for(int k =0; k <=4; k++){for(int w =0; w <=4; w++){if( j >= val2[w][k]){
dp2[i][j][k]=max( dp2[i][j][k],
dp2[i -1][j - val2[w][k]][w]);}}if( k ==1)
dp2[i][j][k]+= a[i][1];if( k ==2)
dp2[i][j][k]+= a[i][2];if( k ==3|| k ==4)
dp2[i][j][k]+= a[i][1]+ a[i][2];}}int ans =-1e9;for(int i =0; i <=4; i++)
ans =max( ans , dp2[n][t][i]);printf("%d\n", ans);}intmain(){scanf("%d%d%d",&n ,&m ,&t );for(int i =1; i <= n ; i++){for(int j =1; j <= m ; j++){scanf("%d",&a[i][j]);}}if( m ==1){do1();}else{do2();}return0;}