[bzoj4945][Noi2017]游戏
题目大意:有$n$个位置,有三种数,每个位置只可以填一种数,$d(d\leqslant8)$个位置有三种选择,其他位置只有两种选择。有一些限制,表示第$i$个位置选了某种数,那么第$j$个位置就只能选规定的数
输出一组合法的选数方案,无解输出$-1$
题解:考虑$d=0$的情况,就是$2-sat$的裸题。
那$d>0$的呢?发现$d\leqslant8$,因为跑一次$2-sat$的复杂度是$O(n+m)(n\leqslant5\times10^4,m\leqslant10^5)$,好像有很大的空间乱搞?若暴力$dfs$每一位选什么,复杂度是$O(3^8(n+m))\approx9.8\times10^8$,过不了。
考虑优化,如果枚举$d$个位置不可以填什么,那么就是$1,2;2,3;1,3$,发现前两种已经包含了$1,2,3$三种方案,于是复杂度成了$O(2^8(n+m))\approx3.8\times10^7$。可以承受,于是就过了
卡点:1.限制条件给的是大写字母,写成小写字母
2.有一个函数因为调试改成了另一个,最后忘记调回来,花了我$1.5h+$的时间
C++ Code:
#include <cstdio>
#include <cstring>
#include <iostream>
#define maxn 50010
#define maxm 100010
int n, nn, D, m, tot;
int X[10], p[maxn];
int a[maxm], b[maxm], c[maxm], d[maxm];
char s[maxn]; int head[maxn << 1], cnt;
struct Edge {
int to, nxt;
} e[maxm << 1];
void addE(int a, int b) {
e[++cnt] = (Edge) {b, head[a]}; head[a] = cnt;
} int DFN[maxn << 1], low[maxn << 1], idx;
int S[maxn << 1], top, res[maxn << 1], CNT;
bool ins[maxn << 1];
inline int min(int a, int b) {return a < b ? a : b;}
void tarjan(int x) {
DFN[x] = low[x] = ++idx; ins[S[++top] = x] = 1;
int y;
for (int i = head[x]; i; i = e[i].nxt)
if (!DFN[y = e[i].to]) tarjan(y), low[x] = std::min(low[x], low[y]);
else if (ins[y]) low[x] = std::min(low[x], DFN[y]);
if (DFN[x] == low[x]) {
CNT++;
do ins[y = S[top--]] = 0, res[y] = CNT; while (x != y);
}
} void init() {
memset(head, 0, sizeof head), cnt = 0;
memset(DFN, 0, sizeof DFN), idx = 0;
CNT = 0;
}
inline bool get(int a, int b) {return b != (a + 1) % 3;}
inline char reget(int a, int b) {return (b + a + 1) % 3 + 'A';}
inline int P(int a, int b) {return a << 1 | b;}
bool work(int T) {
init();
for (int i = 0; i < D; i++) p[X[i]] = bool(T & 1 << i);
for (int i = 0; i < m; i++) {
if (p[a[i]] != b[i]) {
if (p[c[i]] == d[i]) addE(a[i] << 1 | get(p[a[i]], b[i]), a[i] << 1 | !get(p[a[i]], b[i]));
else {
addE(a[i] << 1 | get(p[a[i]], b[i]), c[i] << 1 | get(p[c[i]], d[i])),
addE(c[i] << 1 | !get(p[c[i]], d[i]), a[i] << 1 | !get(p[a[i]], b[i]));
}
}
}
for (int i = 2; i <= nn + 1; i++) {
if (!DFN[i]) tarjan(i);
if (i & 1) if (res[i] == res[i - 1]) return false;
}
for (int i = 1; i <= n; i++) printf("%c", reget(res[i << 1] > res[i << 1 | 1], p[i]));
return true;
} int main() {
scanf("%d%d%s", &n, &D, s + 1); nn = n << 1;
for (int i = 1; i <= n; i++) {
if (s[i] == 'x') X[tot++] = i;
p[i] = s[i] - 'a';
}
scanf("%d", &m);
for (int i = 0; i < m; i++) {
char B, D;
scanf("%d %c %d %c", a + i, &B, c + i, &D);
b[i] = B - 'A';
d[i] = D - 'A';
}
int U = 1 << D;
for (int i = 0; i < U; i++) if (work(i)) return 0;
printf("-1");
return 0;
}
[bzoj4945][Noi2017]游戏的更多相关文章
- [BZOJ4945][Noi2017]游戏 2-sat
对于所有的x,我们枚举他的地图类型,事实上我们只需要枚举前两种地形就可以覆盖所有的情况. 之后就变成了裸的2-sat问题. 对于一个限制,我们分类讨论: 1.h[u]不可选,跳过 2.h[v]不可选, ...
- 【BZOJ4945】[Noi2017]游戏 2-SAT
[BZOJ4945][Noi2017]游戏 题目描述 题解:2-SAT学艺不精啊! 这题一打眼看上去是个3-SAT?哎?3-SAT不是NPC吗?哎?这题x怎么只有8个?暴力走起! 因为x要么不是A要么 ...
- P3825 [NOI2017]游戏
题目 P3825 [NOI2017]游戏 做法 \(x\)地图外的地图好做,模型:\((x,y)\)必须同时选\(x \rightarrow y,y^\prime \rightarrow x^\pri ...
- [Luogu P3825] [NOI2017] 游戏 (2-SAT)
[Luogu P3825] [NOI2017] 游戏 (2-SAT) 题面 题面较长,略 分析 看到这些约束,应该想到这是类似2-SAT的问题.但是x地图很麻烦,因为k-SAT问题在k>2的时候 ...
- BZOJ4945 & 洛谷3825 & UOJ317:[NOI2017]游戏——题解
https://www.lydsy.com/JudgeOnline/problem.php?id=4945 https://www.luogu.org/problemnew/show/P3825 ht ...
- 【bzoj4945】[Noi2017]游戏(搜索+2-sat)
bzoj 洛谷 题意: 现在有\(a,b,c\)三种车,每个赛道可能会存在限制:\(a\)表示不能选择\(a\)类型的赛车,\(b,c\)同理:\(x\)表示该赛道不受限制,但\(x\)类型的个数$\ ...
- 并不对劲的bzoj4945:loj2305:uoj317:p3825[NOI2017]游戏
题目大意 2-SAT,其中有\(d\)(\(d\leq 8\))个点是\(3-SAT\). 题解 枚举\(d\)个点不取三个中(假设三个为\(a,b,c\))的哪一个,然后整体变成做\(2-SAT\) ...
- bzoj3825 NOI2017 游戏
题目背景 狂野飙车是小 L 最喜欢的游戏.与其他业余玩家不同的是,小 L 在玩游戏之余,还精于研究游戏的设计,因此他有着与众不同的游戏策略. 题目描述 小 L 计划进行nn 场游戏,每场游戏使用一张地 ...
- [NOI2017]游戏(2-SAT)
这是约半年前写的题解了,就搬过来吧 感觉这是NOI2017最水的一题(当然我还是不会2333),因为是一道裸的2-SAT.我就是看着这道题学的2-SAT 算法一:暴力枚举.对于abc二进制枚举,对于x ...
随机推荐
- ABAP Table Control
SAP中,Table Control是在Screen中用的最广泛的控件之一了,可以实现对多行数据的编辑. 简单来说,Table Control是一组屏幕元素在Screen上的重复出现,这就是它与普通 ...
- 安装阿里云版Linux云服务器,配置软件
1. 购买域名 2. 购买云服务器ecs 3. 远程访问云服务器并装上Java环境和必备软件 3.1安装远程访问工具 3.2 jdk环境配置 3.3 Mysql依赖关系 重新配置MySQL的远程 ...
- tomcat8080端口占用解决办法
打开控制台,在窗口中输入指令:netstat -ano | findstr 8080 指令的意思是找出占用8080端口的进程pid 上图中表示占用进程pid为23288,然后再次输入指令: ...
- MySQL备份工具percona-xtrabackup安装
1.安装xtrabackup的yum源 rpm -ivh https://www.percona.com/redir/downloads/percona-release/redhat/latest/p ...
- Linux终端显示控制字符
在Linux中, 我们时常要将一个命令的输出作为另外一个命令的输入进行下一步处理操作. 有时, 如果一个命令的输出中有不可见的控制字符时, 有可能会导致后续操作出错. 而这些控制字符很可能是不可打印的 ...
- 内置函数系列之 sorted排序
sorted排序函数语法: sorted(可迭代对象,key=函数(默认为None),reverse=False) 将可 迭代对象的每一个元素传进key后面的函数中,根据函数运算的结果(返回值)进行排 ...
- tcl之array操作
- POJ:3977-Subset(双向搜索)
Subset Time Limit: 30000MS Memory Limit: 65536K Total Submissions: 5961 Accepted: 1129 Description G ...
- dijkstra算法与优先队列
这是鄙人的第一篇技术博客,作为算法小菜鸟外加轻度写作障碍者,写技术博客也算是对自己的一种挑战和鞭策吧~ 言归正传,什么是dijkstra算法呢? -dijkstra算法是一种解决最短路径问题的简单有效 ...
- python基础之布尔运算、集合
布尔值 True 真 False 假 所有的数据类型都自带布尔值,数据只有在0,None和空的时候为False. print(bool()) print(bool()) print(bool('')) ...