首先可以发现这样一个事实:在每次操作当中,都有三张牌是已经固定的,只有两张牌是不确定的,于是我们可以发下每一次操作的状态可以简单的使用这两张牌来描述,于是可以考虑令 \(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. CycleGAN

    目录 概 主要内容 代码 Zhu J., Park T., Isola P. & Efros A. Unpaired Image-to-Image Translation using Cycl ...

  2. Java Web程序设计笔记 • 【第4章 JavaBean和JSP标准动作】

    全部章节   >>>> 本章目录 4.1 JavaBean 4.1.1 JavaBean 概述 4.1.2 JavaBean的重要性 4.1.3 JavaBean的特点 4.1 ...

  3. Java初学者作业——编写Java程序,输入一个数字,实现该数字阶乘的计算。

    返回本章节 返回作业目录 需求说明: 编写Java程序,输入一个数字,实现该数字阶乘的计算.一个数字的阶乘是所有小于及等于该数的正整数的积,自然数n的阶乘写作n! .例如,5的阶乘等于1*2*3*4* ...

  4. 使用 jQuery 基本选择器获取页面元素,然后利用 jQuery 对象的 css() 方法动态设置 <span> 和 <a> 标签的样式

    查看本章节 查看作业目录 需求说明: 使用 jQuery 基本选择器获取页面元素,然后利用 jQuery 对象的 css() 方法动态设置 <span> 和 <a> 标签的样式 ...

  5. 编写Java程序,创建一个 Person 类,该类中有一个类成员变量 country、一个实例变量 name 和另一个实例变量 age。

    返回本章节 返回作业目录 需求说明: 创建一个 Person 类,该类中有一个类成员变量 country.一个实例变量 name 和另一个实例变量 age. country 表示地区,name 表示姓 ...

  6. Hadoop集群安装(真分布式)

    Hadoop真分布式完全集群安装,基于版本2.7.2安装, 在两台Linux机器上面分别安装Hadoop的master和slave节点. 1.安装说明 不管NameNode还是DataNode节点,安 ...

  7. Hbase集群安装Version1.1.5

    Hbase集群安装,基于版本1.1.5, 使用hbase-1.1.5.tar.gz安装包. 1.安装说明 使用外部Zookeeper集群而非Hbase自带zookeeper, 使用Hadoop文件系统 ...

  8. solr -创建 core

    需要进入solr安装目录的bin 里,solr start 启动 后,才可以生成core solr create -c [core的名字] 如:solr create -c mycore1 生成位置在 ...

  9. Ant: macrodef

    <macrodef name="tokenReplace"> <attribute name="subapp"/> <attrib ...

  10. Java 单引号 与 双引号 区别

    双引号,用来引用字符串, 单引号用来表示单个字符.