题目大意
- 给出m种音符,编号为1…m,以及一个m*m的矩阵s。s[i][j]表示音符j出现在i之后时,ij这个组合能得到的分数。
- n个数,每个数num[i]代表一种音符。-1则是可以用任何音符替换,正数则是num[i]本身。
- 求能得到的最大分数
分析
- dp[i][j]表示对于前i个音符,第i个音符用j替换时能得到的最大分数
i和i+1都是-1时
dp[i+1][k] = max(dp[i+1][k],dp[i][j]+s[j][k])
i为-1,i+1为正数时
dp[i+1][num[i]] = max(dp[i+1][num[i]],dp[i][j]+s[j][num[i]])
i为正数,i+1为-1时
dp[i+1][k] = max(dp[i+1][k],dp[i][num[i]]+s[num[i]][k])
i,i+1都是正数时
dp[i+1][num[i+1]] = dp[i][num[i]]+s[num[i]][num[i+1]]
代码
#include <iostream>
#include <cstring>
using namespace std;
const int maxn = 110;
int dp[maxn][maxn];
int s[maxn][maxn];
int num[maxn];
int main()
{
int t , n , m;
cin >> t;
while(cin >> n >> m)
{
for(int i = 1; i <= m; i++)
for(int j = 1; j <= m; j++) cin >> s[i][j];
for(int i = 1; i <= n; i++) cin >> num[i];
memset(dp , 0 , sizeof(dp));
for(int i = 1; i < n; i++) {
if(num[i] < 0) {
for(int j = 1; j <= m; j++) {
if(num[i+1] < 0) for(int k = 1; k <= m; k++) {
dp[i+1][k] = max(dp[i+1][k] , dp[i][j] + s[j][k]);
}
else {
dp[i+1][num[i+1]] = max(dp[i+1][num[i+1]] , dp[i][j] + s[j][num[i+1]]);
}
}
}
else {
if(num[i+1] < 0) for(int k = 1; k <= m; k++) {
dp[i+1][k] = max(dp[i+1][k] , dp[i][num[i]] + s[num[i]][k]);
}
else {
dp[i+1][num[i+1]] = dp[i][num[i]] + s[num[i]][num[i+1]];
}
}
}
if(num[n] > 0) cout << dp[n][num[n]] << endl;
else {
int ma = 0;
for(int i = 1; i <= m; i++) ma = max(ma , dp[n][i]);
cout << ma << endl;
}
}
return 0;
}