hdu 5074 Hatsune Miku (动态规划)

题目大意

  • 给出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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值