LINK


思路

首先如果直接算每一个段有三个决策

左/右 上/下 跨不跨过端点

这样的复杂度是\((2^3)^{22}\),显然是无法接受的

然后考虑怎么优化这个东西

首先左右这个决策是没有意义的

因为无论是左还是右,对答案的相对影响是不变的

其次考虑用a和b分别表示上下和跨不跨过端点的决策

然后退一下就可发现有很多种情况是可以归约的

大概成了这样

void dfs(int tmp, int res) {
if (res >= ans) return;
if (tmp > n) {
ans = res;
return;
}
if (cnt[t[tmp]] == 1 || pre[tmp]) {
dfs(tmp + 1, res);
return;
}
int now;
a[tmp] = 0;
b[tmp] = 0;
now = res;
fu(i, 1, tmp - 1)
if (!(a[i] ^ b[i]) && nxt[i] > tmp && nxt[i] < nxt[tmp]) ++now;
dfs(tmp + 1, now);
a[tmp] = 0;
b[tmp] = 1;
now = res;
fu(i, 1, tmp - 1) {
if ((a[i] ^ b[i]) && nxt[i] > nxt[tmp]) ++now;
if (!(a[i] ^ b[i]) && nxt[i] > tmp) ++now;
}
dfs(tmp + 1, now);
a[tmp] = 1;
b[tmp] = 0;
now = res;
fu(i, 1, tmp - 1)
if ((a[i] ^ b[i]) && nxt[i] > tmp && nxt[i] < nxt[tmp]) ++now;
dfs(tmp + 1, now);
a[tmp] = 1;
b[tmp] = 1;
now = res;
fu(i, 1, tmp - 1) {
if (!(a[i] ^ b[i]) && nxt[i] > nxt[tmp]) ++now;
if ((a[i] ^ b[i]) && nxt[i] > tmp) ++now;
}
dfs(tmp + 1, now);
}

这样是可以得到64分的高分的

但是并不够

继续考虑怎么压缩状态

发现前面的每个已经决策的区间对当前区间的影响只有a和b的异或和

所以每次只枚举a和b的异或和

但是a和b的异或和相等的情况有两种

但是这两种对后面决策的影响都是相同的

所以直接贪心取最小的就可以了

复杂度\(n*2^{n/2}\)


AC代码


//Author: dream_maker
#include<bits/stdc++.h>
using namespace std;
//----------------------------------------------
//typename
typedef long long ll;
//convenient for
#define fu(a, b, c) for (int a = b; a <= c; ++a)
#define fd(a, b, c) for (int a = b; a >= c; --a)
#define fv(a, b) for (int a = 0; a < (signed)b.size(); ++a)
//inf of different typename
const int INF_of_int = 1e9;
const ll INF_of_ll = 1e18;
//fast read and write
template <typename T>
void Read(T &x) {
bool w = 1;x = 0;
char c = getchar();
while (!isdigit(c) && c != '-') c = getchar();
if (c == '-') w = 0, c = getchar();
while (isdigit(c)) {
x = (x<<1) + (x<<3) + c -'0';
c = getchar();
}
if (!w) x = -x;
}
template <typename T>
void Write(T x) {
if (x < 0) {
putchar('-');
x = -x;
}
if (x > 9) Write(x / 10);
putchar(x % 10 + '0');
}
//----------------------------------------------
const int N = 50;
int t[N], n, ans;
int pre[N], nxt[N], last[N], cnt[N];
bool a[N], b[N], mark[N];
//a 走上面(0)还是下面(1)
//b 不跨过(0)还是跨过(1)
int T;
/*void dfs(int tmp, int res) {
if (res >= ans) return;
if (tmp > n) {
ans = res;
return;
}
if (cnt[t[tmp]] == 1 || pre[tmp]) {
dfs(tmp + 1, res);
return;
}
int now;
a[tmp] = 0;
b[tmp] = 0;
now = res;
fu(i, 1, tmp - 1)
if (!(a[i] ^ b[i]) && nxt[i] > tmp && nxt[i] < nxt[tmp]) ++now;
dfs(tmp + 1, now);
a[tmp] = 0;
b[tmp] = 1;
now = res;
fu(i, 1, tmp - 1) {
if ((a[i] ^ b[i]) && nxt[i] > nxt[tmp]) ++now;
if (!(a[i] ^ b[i]) && nxt[i] > tmp) ++now;
}
dfs(tmp + 1, now);
a[tmp] = 1;
b[tmp] = 0;
now = res;
fu(i, 1, tmp - 1)
if ((a[i] ^ b[i]) && nxt[i] > tmp && nxt[i] < nxt[tmp]) ++now;
dfs(tmp + 1, now);
a[tmp] = 1;
b[tmp] = 1;
now = res;
fu(i, 1, tmp - 1) {
if (!(a[i] ^ b[i]) && nxt[i] > nxt[tmp]) ++now;
if ((a[i] ^ b[i]) && nxt[i] > tmp) ++now;
}
dfs(tmp + 1, now);
}*/
void dfs(int tmp, int res) {
if (res >= ans) return;
if (tmp > n) {
ans = res;
return;
}
if (cnt[t[tmp]] == 1 || pre[tmp]) {
dfs(tmp + 1, res);
return;
}
int now1, now2;
mark[tmp] = 0;
now1 = now2 = res;
fu(i, 1, tmp - 1) {
if (!mark[i] && nxt[i] > tmp && nxt[i] < nxt[tmp]) ++now1;
if (!mark[i] && nxt[i] > nxt[tmp]) ++now2;
if (mark[i] && nxt[i] > tmp) ++now2;
}
dfs(tmp + 1, min(now1, now2));
mark[tmp] = 1;
now1 = now2 = res;
fu(i, 1, tmp - 1) {
if (mark[i] && nxt[i] > tmp && nxt[i] < nxt[tmp]) ++now1;
if (mark[i] && nxt[i] > nxt[tmp]) ++now2;
if (!mark[i] && nxt[i] > tmp) ++now2;
}
dfs(tmp + 1, min(now1, now2));
}
void solve() {
Read(n);
fu(i, 1, n) pre[i] = nxt[i] = last[i] = cnt[i] = 0;
fu(i, 1, n) {
Read(t[i]);
++cnt[t[i]];
if (last[t[i]]) {
pre[i] = last[t[i]];
nxt[last[t[i]]] = i;
} else {
last[t[i]] = i;
}
}
ans = INF_of_int;
dfs(1, 0);
printf("%d\n", ans);
}
int main() {
freopen("input.txt","r",stdin);
Read(T);
while (T--) solve();
return 0;
}

最新文章

  1. java Io流向指定文件输入内容
  2. Linux编程环境
  3. 基于Attribute的Web API路由设置
  4. 中国天气预报数据API收集
  5. [转]优秀Python学习资源收集汇总
  6. [原]在Fedora中编译Libevent测试实例
  7. 关于python中的unicode字符串的使用
  8. NWERC 2012 Problem A Admiral
  9. (转)单例模式(Singleton)
  10. oschina插件和扩展
  11. C#隐式转换和显示转换举例--C#基础
  12. Oracle 报错ORA-00904:标示符无效
  13. 一段JAVA代码了解多线程,JUC、CAS原子性操作。
  14. java web的MVC框架,el表达式,servlet,jstl表达式
  15. 1.1.21 Word修改文章目录
  16. 【python深入】单例模式
  17. .Net开源框架列表
  18. 我的software
  19. CentOS 7源码安装zabbix
  20. Github忽略keil工程生成的链接、编译等文件

热门文章

  1. 测试Python类成员的单下划线,双下划线,两头下划线的区别
  2. du,df 磁盘管理
  3. UWP C# 调用 C++/CX
  4. PHP中用下划线开头的含义
  5. 身份证真实性校验js、mini ui身份证长度正则验证
  6. 转:kafka入门
  7. poj 1379 Run Away 模拟退火 难度:1
  8. Markdown_01_基础语法
  9. 在QT中使用静态对象
  10. SpringInAction--面向切片的Spring以及如何使用注解创建切面