题目链接:Hatsune Miku
解题思路:动态规划,dp[i][j]表示长度为i,以字符j结尾的最大值。那么状态转移方程如下:
seq[MAX_N]数组代表序列的情况,例如样例2中的{-1 -1 5 -1 4 -1 -1 -1 4 -1}
如果i的位置不是自由位置
1.i - 1的位置不是自由位置 dp[i][seq[i]] = max(dp[i][seq[i]], dp[i - 1][seq[i - 1]] + v[seq[i - 1]][seq[i]];
2.i - 1的位置 是自由位置 dp[i][seq[i]] = max(dp[i][seq[i]], dp[i - 1][j] + v[j][seq[i]];
如果i的位置是自由位置
1.i - 1的位置不是自由位置 dp[i][j] = max(dp[i][j], dp[i - 1][seq[i - 1]] + v[seq[i - 1]][j];
2.i - 1的位置 是自由位置 dp[i][j] = max(dp[i][j], dp[i - 1][k] + v[k][j];
其中2 <= i <= n, 1 <= j, k <= m。
最终的答案就在dp[n][i]( 1 <= i <= m)中最大的。
#include<cstdio>
#include<iostream>
#include<cstring>
#define MAX_N 110
#define MAX_M 55
using namespace std;
int seq[MAX_N];
int dp[MAX_N][MAX_M], v[MAX_N][MAX_M];
int n, m;
void init(){
}
void slove(){
int i, j, k;
memset(dp, 0, sizeof(dp));
for(i = 2; i <= n; i++){
if(seq[i] != -1){
if(seq[i - 1] != -1){
dp[i][seq[i]] = max(dp[i][seq[i]], dp[i - 1][seq[i - 1]] + v[seq[i - 1]][seq[i]]);
}
else{
for(k = 1; k <= m; k++){
dp[i][seq[i]] = max(dp[i][seq[i]], dp[i - 1][k] + v[k][seq[i]]);
}
}
}
else{
for(j = 1; j <= m; j++){
if(seq[i - 1] != -1){
dp[i][j] = max(dp[i][j], dp[i - 1][seq[i - 1]] + v[seq[i - 1]][j]);
}
else{
for(k = 1; k <= m; k++){
dp[i][j] = max(dp[i][j], dp[i - 1][k] + v[k][j]);
}
}
}
}
}
}
int main(){
int i, j, k, t;
cin >> t;
while(t--){
cin >> n >> m;
init();
for(i = 1; i <= m; i++){
for(j = 1; j <= m; j++){
cin >> v[i][j];
}
}
for(i = 1; i <= n; i++){
cin >> seq[i];
}
slove();
int ans = -1;
for(i = 1; i <= m; i++){
if(dp[n][i] > ans){
ans = dp[n][i];
}
}
cout << ans << endl;
}
return 0;
}