首先可以发现这样一个事实:在每次操作当中,都有三张牌是已经固定的,只有两张牌是不确定的,于是我们可以发下每一次操作的状态可以简单的使用这两张牌来描述,于是可以考虑令 \(dp_{i, j, k}\) 表示当前进行到第 \(i\) 轮操作,当前剩下来的两张牌分别为 \(j, k\) 的最大得分。直接转移是 \(O(\binom{5}{3} = 10)\) 的,因此总复杂度是 \(O(n ^ 3 \times 10)\) 的。还需要进一步优化这个 \(dp\),但是貌似这个状态是不能压缩的,于是可以考虑一下转移的过程。因为有三张牌是已经确定的,可以发现这样一个事实,如果留下来的两张牌都不是这确定的三张牌,那么转移的过程相当于将上一轮的 \(dp\) 值继承过来再整体加上一个数,我们直接使用上一轮的 \(dp\) 值并记录总体增量就能将这一部分的复杂度做到 \(O(1)\);那么如果留下来的牌中至少有一张是已经确定的,那么实际上需要修改的 \(dp\) 状态也只有 \(O(n)\) 个,于是这个优化转移的想法看起来是很可行的。下面来具体讨论一下。(下面令 \(dp\) 为当前轮的 \(dp\) 值,\(L\) 为上一轮的 \(dp\) 值)

我们令之前继承过来的两张牌为 \(x, y\) 已经固定的牌为 \(A, B, C\)。假如删掉的牌为 \(A, B, C\),如果 \(A, B, C\) 不完全相等,那么就会有转移 \(dp_{x, y} = L_{x, y}\),相当于没有变,不需要修改,保证每次开始时 \(dp = L\) 即可;如果 \(A = B = C\),就有转移 \(dp_{x, y} = L_{x, y} + 1\) 相当于将所有位置整体加 \(1\),但会有这样一个问题,当前的一些状态可能是不合法的,但之后可能合法,它也需要加上之前的增加量,这样看来似乎我们不得不每次修改都全体加 \(1\),但实际上这是不必要的。仔细想想,如果 \(A = B = C\) 我们为什么不直接再最开始就删去直接对所有贡献 \(+1\) 呢,于是我们事先处理好 \(A = B = C\) 的情况并将这种情况删去即可。

接下来是 \(x, y\) 中一个带上 \(A, B, C\) 中的两个删去的转移。以带 \(A, B\) 为例就会有:

\[dp_{C, x} = \max\limits_{i = 1} ^ n\{L_{x, i}\}
\]

直接对于每一行维护 \(S_x = \max\limits_{i = 1} ^ n dp_{x, i}\) 即可。特别的如果 \(A = B\),那么还有转移 \(dp_{C, x} = L_{A, x} + 1\)。

最后是 \(x, y\) 都会被删去的情况,以 \(A, B\) 留下为例,会有转移:

\[dp_{A, B} = \max\{\max\limits_{i = 1, j = 1} ^ n L_{i, j}, L_{C, C} + 1\}
\]

于是只需要维护全局最大值 \(Max\) 即可。最后我们需要将 \(L, S, Max\) 修改,直接在上述转移时记录修改了那些位置最后直接暴力修改即可。

#include<bits/stdc++.h>
using namespace std;
#define rep(i, l, r) for(int i = l; i <= r; ++i)
const int N = 2000 + 5;
const int M = 20000 + 5;
const int inf = 1000000000;
struct Modify{
int x, y;
}up[M];
int n, m, ans, Max, a[N * 3], b[N], f[N], S[N], L[N][N], dp[N][N];
int read(){
char c; int x = 0, f = 1;
c = getchar();
while(c > '9' || c < '0'){ if(c == '-') f = -1; c = getchar();}
while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
return x * f;
}
int chkmax(int &a, int b){
return a = max(a, b);
}
int main(){
n = read();
rep(i, 1, n * 3) a[i] = read();
rep(i, 1, n - 1){
int Fi = 2 + (i - 1) * 3;
if((a[Fi + 1] == a[Fi + 2]) && (a[Fi + 2] == a[Fi + 3])) ++ans, f[i] = 1;
}
rep(i, 1, n) rep(j, 1, n) dp[i][j] = L[i][j] = S[i] = -inf;
L[a[1]][a[2]] = L[a[2]][a[1]] = dp[a[1]][a[2]] = dp[a[2]][a[1]] = S[a[1]] = S[a[2]] = 0;
rep(i, 1, n - 1){
if(f[i]) continue;
int Fi = 2 + (i - 1) * 3; m = 0;
dp[a[Fi + 2]][a[Fi + 1]] = chkmax(dp[a[Fi + 1]][a[Fi + 2]], max(Max, L[a[Fi + 3]][a[Fi + 3]] + 1));
dp[a[Fi + 3]][a[Fi + 1]] = chkmax(dp[a[Fi + 1]][a[Fi + 3]], max(Max, L[a[Fi + 2]][a[Fi + 2]] + 1));
dp[a[Fi + 3]][a[Fi + 2]] = chkmax(dp[a[Fi + 2]][a[Fi + 3]], max(Max, L[a[Fi + 1]][a[Fi + 1]] + 1));
up[++m].x = a[Fi + 1], up[m].y = a[Fi + 2];
up[++m].x = a[Fi + 1], up[m].y = a[Fi + 3];
up[++m].x = a[Fi + 2], up[m].y = a[Fi + 3];
int A, B, C; b[1] = a[Fi + 1], b[2] = a[Fi + 2], b[3] = a[Fi + 3];
sort(b + 1, b + 3 + 1), A = b[1], B = b[2], C = b[3];
if(B == C) swap(A, C);
rep(j, 1, n) if(S[j] >= 0){
up[++m].x = j, up[m].y = A, up[++m].x = j, up[m].y = B, up[++m].x = j, up[m].y = C;
dp[A][j] = chkmax(dp[j][A], S[j]);
dp[B][j] = chkmax(dp[j][B], S[j]);
dp[C][j] = chkmax(dp[j][C], S[j]);
}
if(A == B){
rep(j, 1, n) if(L[j][A] >= 0){
up[++m].x = j, up[m].y = C;
dp[j][C] = chkmax(dp[C][j], L[j][A] + 1);
}
}
rep(j, 1, m){
int x = up[j].x, y = up[j].y;
L[x][y] = L[y][x] = dp[x][y];
Max = max(Max, dp[x][y]), S[x] = max(S[x], dp[x][y]), S[y] = max(S[y], dp[x][y]);
}
}
printf("%d", max(Max, dp[a[n * 3]][a[n * 3]] + 1) + ans);
return 0;
}

AT [ABC176F] Brave CHAIN的更多相关文章

  1. zipkin-client:brave核心代码思路整理

    Zipkin是分布式跟踪系统. 简单地理解,可以将Zipkin分为两部分. 一部分为Zipkin Server,其负责接受存储应用程序处理耗时数据,以及UI展示. 另一部分为Zipkin Client ...

  2. HDU 1856 Brave Game(巴什博奕)

    十年前读大学的时候,中国每年都要从国外引进一些电影大片,其中有一部电影就叫<勇敢者的游戏>(英文名称:Zathura),一直到现在,我依然对于电影中的部分电脑特技印象深刻. 今天,大家选择 ...

  3. STM32用JLINK 烧写程序时出现NO Cortex-m device found in JTAG chain现象和解决方案

    现象 CPU: STM32107VC 用JLINK 烧写程序时出现NO Cortex-m device found in JTAG chain 如图无法查找到硬件就是CPU 提示1:NO Cortex ...

  4. 责任链模式/chain of responsibility/行为型模式

    职责链模式 chain of responsibility 意图 使多个对象都有机会处理请求,从而避免请求的发送者和接受者之间的耦合关系.将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处 ...

  5. 树形DP+DFS序+树状数组 HDOJ 5293 Tree chain problem(树链问题)

    题目链接 题意: 有n个点的一棵树.其中树上有m条已知的链,每条链有一个权值.从中选出任意个不相交的链使得链的权值和最大. 思路: 树形DP.设dp[i]表示i的子树下的最优权值和,sum[i]表示不 ...

  6. arm,iptables: No chain/target/match by that name.

    最近由于项目需要,需要打开防火墙功能. 公司有 arm linux 3.0x86 linux 3.2x86 linux 2.4 的三个嵌入式.都需要打开防火墙功能. 执行“whereis iptabl ...

  7. C#设计模式系列:职责链模式(Chain of Responsibility)

    1.职责链模式简介 1.1>.定义 职责链模式是一种行为模式,为解除请求的发送者和接收者之间的耦合,而使多个对象都有机会处理这个请求.将这些对象连接成一条链,并沿着这条链传递该请求,直到有一个对 ...

  8. [工作中的设计模式]责任链模式chain

    一.模式解析 责任链模式是一种对象的行为模式.在责任链模式里,很多对象由每一个对象对其下家的引用而连接起来形成一条链.请求在这个链上传递,直到链上的某一个对象决定处理此请求.发出这个请求的客户端并不知 ...

  9. track message forwards, avoiding request loops, and identifying the protocol capabilities of all senders along the request/response chain

    https://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html The TRACE method is used to invoke a remote, ...

随机推荐

  1. 【机器学*】k*邻算法-01

    k临*算法(解决分类问题): 已知数据集,以及该数据对应类型 给出一个数据x,在已知数据集中选择最接*x的k条数据,根据这k条数据的类型判断x的类型 具体实现: from numpy import * ...

  2. CoGAN

    目录 概 主要内容 代码 Liu M., Tuzel O. Coupled Generative Adversarial Networks. NIPS, 2016. 概 用GAN和数据(从边缘分布中采 ...

  3. Java语言程序设计复习提纲

     这是我在准备Java考试时整理的提纲,如果是通过搜索引擎搜索到这篇博客的师弟师妹,建议还是先参照PPT和课本,这个大纲也不是很准确,自己总结会更有收获,多去理解含义,不要死记硬背,否则遇到概念辨析题 ...

  4. CS5213demoboard设计电路|DMI转VGA带II2S音频输出转接线|CS5213方案

    CS5213是台湾CAPSTONE瑞奇达推出的一款HDMI(高清多媒体接口)到VGA转换芯片. CS5213设计HDMI转VGA带II2S转接线产品特性: ◇将完整的HDMI信号转换为VGA输出◇支持 ...

  5. <数据结构>XDOJ.322关键路径长度

    问题与解答 问题描述 计算AOE-网中关键路径的长度. 输入格式 输入数据第一行是一个正整数,表示图中的顶点个数n(顶点将分别按0,1,-,n-1进行编号),顶点数不超过100,其中0为源点,n-1为 ...

  6. 编写Java程序,定义士兵类(Soldiers)并初始化5个士兵对象。

    返回本章节 返回作业目录 需求说明: 创建士兵类(Soldiers),定义有一个String类型参数name,代表士兵的姓名,两个int类型变量x和y,分别表示士兵所在的坐标位置,x代表横坐标,y代表 ...

  7. SpringBoot集成Actuator监控管理

    1.说明 本文详细介绍Spring Boot集成Actuator监控管理的方法, 基于已经创建好的Spring Boot工程, 然后引入Actuator依赖, 介绍监控管理相关功能的使用. Sprin ...

  8. ElasticSearch启动失败:master not discovered or elected yet, an election requires at least X nodes with ids from [XXXXX]

    这个问题困扰过我一段时间,它其实是说未能选举出一个主节点,最后在官网教程中找到答案. 首先是启动(链接): 总结下来就是,如果ES集群是第一次启动,那么需要 cluster.initial_maste ...

  9. Swoole 中使用通道(Channel)实现协程间通讯(消息队列)

    通道 Coroutine\Channel 使用本地内存,不同的进程之间内存是隔离的. 只能在同一进程的不同协程内进行 push 和 pop 操作. Co::set(['hook_flags'=> ...

  10. 论文翻译:2021_Semi-Blind Source Separation for Nonlinear Acoustic Echo Cancellation

    论文地址:https://ieeexplore.ieee.org/abstract/document/9357975/ 基于半盲源分离的非线性回声消除 摘要: 当使用非线性自适应滤波器时,数值模型与实 ...