LOJ2323. 「清华集训 2017」小 Y 和地铁 【搜索】【思维】【好】
思路
首先如果直接算每一个段有三个决策
左/右 上/下 跨不跨过端点
这样的复杂度是\((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;
}
LOJ2323. 「清华集训 2017」小 Y 和地铁 【搜索】【思维】【好】的更多相关文章
- [LOJ#2323]「清华集训 2017」小Y和地铁
[LOJ#2323]「清华集训 2017」小Y和地铁 试题描述 小Y是一个爱好旅行的OIer.一天,她来到了一个新的城市.由于不熟悉那里的交通系统,她选择了坐地铁. 她发现每条地铁线路可以看成平面上的 ...
- Loj #2324. 「清华集训 2017」小 Y 和二叉树
Loj #2324. 「清华集训 2017」小 Y 和二叉树 小Y是一个心灵手巧的OIer,她有许多二叉树模型. 小Y的二叉树模型中,每个结点都具有一个编号,小Y把她最喜欢的一个二叉树模型挂在了墙上, ...
- loj #2325. 「清华集训 2017」小Y和恐怖的奴隶主
#2325. 「清华集训 2017」小Y和恐怖的奴隶主 内存限制:256 MiB时间限制:2000 ms标准输入输出 题目类型:传统评测方式:文本比较 题目描述 "A fight? Co ...
- [LOJ#2324]「清华集训 2017」小Y和二叉树
[LOJ#2324]「清华集训 2017」小Y和二叉树 试题描述 小Y是一个心灵手巧的OIer,她有许多二叉树模型. 小Y的二叉树模型中,每个结点都具有一个编号,小Y把她最喜欢的一个二叉树模型挂在了墙 ...
- loj2324 「清华集训 2017」小 Y 和二叉树
https://loj.ac/problem/2324 太智障,一开始以为中序遍历的第一个点一定是一个叶子,想了个贪心.然而,手算了一下,第一个点都过不了啊. input 5 2 3 4 1 3 3 ...
- LOJ2324「清华集训 2017」小Y和二叉树
题目链接 瞎jb贪一发就过了.首先度数<=2且编号最小的点一定是中序遍历最靠前的点,我们从这个点开始dfs一遍算出子树中度数<=2且编号最小的点记为\(f(i)\),然后从这个点开始一步一 ...
- 【loj2325】「清华集训 2017」小Y和恐怖的奴隶主 概率dp+倍增+矩阵乘法
题目描述 你有一个m点生命值的奴隶主,奴隶主受伤未死且当前随从数目不超过k则再召唤一个m点生命值的奴隶主. T次询问,每次询问如果如果对面下出一个n点攻击力的克苏恩,你的英雄期望会受到到多少伤害. 输 ...
- LOJ2324. 「清华集训 2017」小 Y 和二叉树【贪心】【DP】【思维】【好】
LINK 思路 首先贪新的思路是处理出以一个节点为根所有儿子的子树中中序遍历起始节点最小是多少 然后这个可以两次dfs来DP处理 然后就试图确定中序遍历的第一个节点 一定是siz<=2的编号最小 ...
- LibreOJ #2325. 「清华集训 2017」小Y和恐怖的奴隶主(矩阵快速幂优化DP)
哇这题剧毒,卡了好久常数才过T_T 设$f(i,s)$为到第$i$轮攻击,怪物状态为$s$时对boss的期望伤害,$sum$为状态$s$所表示的怪物个数,得到朴素的DP方程$f(i,s)=\sum \ ...
随机推荐
- Kaggle 项目之 Digit Recognizer
train.csv 和 test.csv 包含 1~9 的手写数字的灰度图片.每幅图片都是 28 个像素的高度和宽度,共 28*28=784 个像素点,每个像素值都在 0~255 之间. train. ...
- Tomcat 环境搭建
最近在工作之余,看到了一些 Tomcat 的基础资料,感觉蛮好.同时也回忆起自己刚毕业要参加工作那会对 Tomcat 也是各种资料各种查,实属不易.为此,针对最近整理的一些基础,把 Tomcat 基本 ...
- 揭开A*算法的神秘面纱
揭开A*算法的神秘面纱 一.总结 一句话总结:f(n)=g(n)+h(n) 这个算法有点像BFS的优化算法. g(n)为起点到当前方格的距离,这个是已知的. h(n)为当前方格到终点的距离,这个简单点 ...
- MySQL设置某一字段默认为0,但是插入数据化却显示为null
1.MySQL字段默认的含义:在插入时不指定该字段的值:2.以mybatis举例,如果是插入实体,那么为空的字段就会插入空:3.如果不想mybatis等持久化工具插入空,可以尝试insertSelec ...
- 设计模式--状态模式C++实现
1定义 当一个状态的内在状态改变时允许其行为改变,这个对象看起来像改变了其类 2类图 角色分析 State抽象状态角色,接口或者抽象类,负责状态定义,并且封装环境角色以实现状态切换 ConcreteS ...
- 9.深入理解AbstractQueuedSynchronizer(AQS)
1. AQS简介 在上一篇文章中我们对lock和AbstractQueuedSynchronizer(AQS)有了初步的认识.在同步组件的实现中,AQS是核心部分,同步组件的实现者通过使用AQS提供的 ...
- Hibernate中"二级缓存"配置
实体类 : package cn.happy.entity; public class Emp { private Integer empNo; private String empName; pub ...
- 常用git命令(一)
git add 命令. 这是个多功能命令:可以用它开始跟踪新文件,或者把已跟踪的文件放到暂存区,还能用于合并时把有冲突的文件标记为已解决状态等. 将这个命令理解为“添加内容到下一次提交中”而不是“将一 ...
- 【MySQL】CSV 文件导入MySQL
此问题是前几天整理数据的时候碰到的,数据存在 CSV文件中(200多万记录),通过python 往数据库中导入太慢了,后来使用MySQL 中自带的命令 LOAD DATA INFILE, 30多秒就能 ...
- 2: 使用Prism初始化程序 Initializing Applications Using the Prism Library 5.0 for WPF(英汉对照版)
This topic addresses what needs to happen to get a Prism for WPF application up and running. A Prism ...