首页 > 其他 > 详细

D. Genius DP

时间:2021-04-12 22:52:21      阅读:58      评论:0      收藏:0      [点我收藏+]

D. Genius DP

题目大意:

\(n\) 个问题,对于第 \(i\) 个问题 \(c_i = 2^i\)\(tag_i\)\(s_i\) ,一开始你有的 \(IQ = 0\) ,你可以从 \(u\) 走到 \(v\) 当且仅当 \(IQ<|c_i-c_j|\) 并且 \(tag_i!=tag_j\) ,同时你可以获得 \(|s_i-s_j|\) 的分数。问你最多可以获得多少分数?

题解:

首先推荐一篇写的很好的题解:https://blog.csdn.net/qq_35577488/article/details/115018266

定义:\(dp[i]\) 表示 \(i\) 是最后一个被访问的点,此时获得的最大的分数。

\((i,j,w)\)\((j,i,w)\) 分数是一样的,但是状态是不一样的,假设 \(i>j\)

\(dp[i] = max(dp[i],dp[j]+w)\) 需要注意的是: \(dp[i]\) 其实隐含着从 \([j+1,i-1]\) 这个区间转移到 \(j\) ,然后再从 \(j\) 转移到 \(i\)

\(dp[j] = max(dp[j],dp[i]+w)\) 需要注意的是:\(dp[j]\) 也隐含着从 \([j+1,i-1]\) 这个区间转移到 \(i\) ,然后再从\(i\) 转移到 \(j\)

所以 \(i\) 需要从 \([2,n]\) 遍历,而 \(j\) 需要从 \([i-1,1]\) 遍历。

如果 \(j\)\([1,j-1]\) 这样的遍历顺序,那么就会出现问题。

#include <bits/stdc++.h>
using namespace std;
const int maxn = 5e3 + 10;
typedef long long ll;
int a[maxn],tag[maxn];
ll dp[maxn];

int main(){
    int T;
    scanf("%d",&T);
    while(T--) {
        int n;
        scanf("%d", &n);
        for (int i = 1; i <= n; i++) scanf("%d", &tag[i]);
        for (int i = 1; i <= n; i++) scanf("%d", &a[i]), dp[i] = 0;
        ll ans = 0;
        for (int i = 2; i <= n; i++) {
            for (int j = i - 1; j >= 1; j--) {
                if (tag[i] ^ tag[j]) {
                    long long temp = dp[i], w = abs(a[i] - a[j]);
                    dp[i] = max(dp[i], dp[j] + w);
                    dp[j] = max(dp[j], temp + w);
                    ans = max(ans,dp[i]);
                    ans = max(ans,dp[j]);
                }
            }
        }
        printf("%lld\n",ans);
    }
    return 0;
}

D. Genius DP

原文:https://www.cnblogs.com/EchoZQN/p/14650280.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!