栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

[nk] 糟糕的打谱员 线性DP

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

[nk] 糟糕的打谱员 线性DP

前言

线性DP是世界上最难的算法!!(我在口胡)
前言 : https://ac.nowcoder.com/acm/contest/11215/C

思路

看完该题之后 (问的什么鬼 贪心?排序之后交替拿? 样例都没过笑死 QAQ)

认真分析一波,转换模型

这题其实再问 满足条件的最长序列长度

条件就是 当前的 c和a 与上一个 不同 :(DP的样子出来了是不是)

因此需要求的状态就是 f[i]即当前最长的序列长度

状态转移 :

因为这个可以乱序拿 我们不能从 i-1或者 i 之前的直接枚举出来

我们可以通过 a 来枚举 (因为他才10)

所以我们可以通过 ^(异或) 以及一个 pre 数组 枚举a 然后来进行状态转移

即 f [ i ] = max ⁡ ( f [ i ] , f [ pre ⁡ [ c [ i ] ∧ 1 ] [ j ] ] + 1 ) f[i]=max left(f[i], fleft[operatorname{pre}left[c[i]^{wedge} 1right][j]right]+1right) f[i]=max(f[i],f[pre[c[i]∧1][j]]+1)

因此这样子就简单的推下来了

(可真 简单 是吧?)

CODE
#include 
using namespace std;
const int N = 3e5+10;
int t,n;
int c[N],a[N],f[N],pre[N][15];
void solve()
{
    memset(f,0,sizeof f);
    memset(pre,0,sizeof pre);

    int ans = 0 ;
    cin>>n;
    for(int i=1;i<=n;i++)
    cin>>c[i]>>a[i];

    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=10;j++)
        {
            if(a[i] == j) continue;
            f[i] = max(f[i],f[pre[c[i]^1][j]]+1);
            pre[c[i]][a[i]] = i;
            ans = max(ans,f[i]);
        }
    }
    cout<>t;
    while(t -- )
    solve();
    return 0;
}
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/296901.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号