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

最新文章

  1. shell两数之间的算术运算
  2. tomcat处理中文文件名的访问(乱码)
  3. Windows Server 2008 R2域控组策略设置禁用USB
  4. iOS开发:http中的get和post请求
  5. iOS钥匙串
  6. javaweb学习总结(二十二)——基于Servlet+JSP+JavaBean开发模式的用户登录注册
  7. 使用StarUML创建类图
  8. MATLAB实现矩阵分块相乘
  9. NDK 编译可执行程序
  10. 【HDOJ】1230 火星A+B
  11. udhcpc和udhcpd移植
  12. OneAPM Cloud Test——系统性能监控神器
  13. cookie 和 session
  14. Binary Tree(二叉树+思维)
  15. EF5.0默认不支持DB First了?
  16. go实例之线程池
  17. 将项目Demo上传到Github上的操作步骤
  18. k8s--如何使用Namespaces
  19. JS 遍历JSON中每个key值
  20. 记XX2013届优秀毕业生评选(请重视在公司展现自己,重视业绩參评过程,非技术贴)

热门文章

  1. matplotlib 高阶之patheffect (阴影,强调)
  2. 图像处理opencv-Rect 排序、合并[转]
  3. 在pycharm中创建py文件——创建你的第一个项目
  4. PHP 的扩展类型及安装方式
  5. Redis OM .NET Redis对象映射框架
  6. 关于java的Excel导入导出之easypoi
  7. Flask_响应(四)
  8. react中create-react-app配置antd按需加载(方法二)
  9. 第10组 Alpha冲刺 (2/6)
  10. Word2010制作自动目录