Luogu3825[NOI2017] 游戏

原题链接:https://www.luogu.org/problemnew/show/P3825

游戏

题目背景

狂野飙车是小 L 最喜欢的游戏。与其他业余玩家不同的是,小 L 在玩游戏之余,还精于研究游戏的设计,因此他有着与众不同的游戏策略。

题目描述

小 L 计划进行 n n 场游戏,每场游戏使用一张地图,小 L 会选择一辆车在该地图上完成游戏。

小 L 的赛车有三辆,分别用大写字母A、B、C表示。地图一共有四种,分别用小写字母x、a、b、c表示。其中,赛车A不适合在地图a上使用,赛车B不适合在地图b上使用,赛车C不适合在地图c上使用,而地图x则适合所有赛车参加。适合所有赛车参加的地图并不多见,最多只会有d张。

n 场游戏的地图可以用一个小写字母组成的字符串描述。例如:S=xaabxcbc表示小 L 计划进行 8 8 场游戏,其中第 1 场和第 5 5 场的地图类型是x,适合所有赛车,第 2 场和第 3 3 场的地图是a,不适合赛车A,第 4 场和第 7 7 场的地图是b,不适合赛车B,第 6 场和第 8 8 场的地图是c,不适合赛车C。

小 L 对游戏有一些特殊的要求,这些要求可以用四元组 (i,hi,j,hj)来描述,表示若在第 i i 场使用型号为 hi的车子,则第 j j 场游戏要使用型号为 hj的车子。

你能帮小 L 选择每场游戏使用的赛车吗?如果有多种方案,输出任意一种方案。如果无解,输出 “-1’’(不含双引号)。

输入输出格式
输入格式:

输入第一行包含两个非负整数 n,d n , d

输入第二行为一个字符串 S S n,d,S 的含义见题目描述,其中 S S 包含n 个字符,且其中恰好 d d 个为小写字母 x

输入第三行为一个正整数 m m ,表示有 m 条用车规则。接下来 m m 行,每行包含一个四元组 i,hi,j,hj,其中 i,j i , j 为整数, hi,hj h i , h j 为字符a、b或c,含义见题目描述。

输出格式:

输出一行。

若无解输出 “-1’’(不含双引号)。

若有解,则包含一个长度为 n n 的仅包含大写字母A、B、C的字符串,表示小 L 在这 n 场游戏中如何安排赛车的使用。如果存在多组解,输出其中任意一组即可。

输入输出样例
输入样例#1:

3 1
xcc
1
1 A 2 B

输出样例#1:

ABA

输入样例#2:

100 8
bbccxabbcxaabbabcaaxbxaaccbcxcccbaccbccbbacaabcbcabxccbbabccabcabbacbbbbabccaabcaaacbabcacxabaxcabbb
200
61 B 14 A
34 B 76 B
17 B 13 A
5 C 2 C
90 A 73 C
6 B 72 C
21 A 1 C
54 B 96 B
2 C 44 B
7 A 32 B
71 A 83 C
65 A 21 A
32 B 45 B
18 B 34 B
51 A 13 A
89 C 63 B
26 B 22 C
38 B 94 C
86 C 95 C
95 C 76 B
67 B 100 A
99 A 40 A
35 A 53 B
47 B 41 A
36 B 69 A
75 B 52 B
90 A 7 A
96 B 59 A
92 C 98 C
23 B 80 B
13 A 48 A
54 B 2 C
93 C 39 A
96 B 87 A
66 A 15 C
38 B 16 A
54 B 41 A
67 B 40 A
45 B 66 A
32 B 80 B
34 B 59 A
31 B 75 B
65 A 78 C
34 B 56 C
28 B 8 A
87 A 40 A
56 C 40 A
93 C 100 A
31 B 41 A
39 A 48 A
55 C 28 B
64 C 60 B
69 A 82 C
99 A 13 A
47 B 30 B
45 B 33 A
88 A 75 B
59 A 4 B
53 B 44 B
11 B 80 B
52 B 50 C
71 A 7 A
41 A 63 B
58 A 23 B
55 C 96 B
71 A 9 A
24 B 34 B
68 B 92 C
15 C 18 B
56 C 14 A
98 C 39 A
27 A 56 C
95 C 31 B
100 A 57 C
62 C 51 A
6 B 32 B
9 A 99 A
46 C 66 A
21 A 1 C
14 A 91 C
61 B 37 A
76 B 81 B
80 B 43 B
98 C 87 A
56 C 49 A
39 A 5 C
88 A 65 A
60 B 34 B
95 C 11 B
90 A 56 C
61 B 48 A
87 A 21 A
46 C 84 A
87 A 18 B
36 B 52 B
61 B 97 B
40 A 36 B
77 C 71 A
78 C 26 B
57 C 85 C
75 B 95 C
41 A 14 A
59 A 1 C
47 B 5 C
11 B 88 A
60 B 24 B
35 A 98 C
44 B 32 B
2 C 69 A
33 A 62 C
65 A 72 C
97 B 93 C
94 C 27 A
19 C 51 A
63 B 45 B
97 B 4 B
10 A 8 A
4 B 56 C
12 C 66 A
95 C 72 C
41 A 30 B
69 A 85 C
13 A 2 C
18 B 14 A
71 A 3 B
75 B 87 A
26 B 24 B
80 B 20 B
2 C 50 C
70 A 64 C
46 C 18 B
67 B 55 C
25 B 22 C
62 C 37 A
40 A 56 C
60 B 80 B
37 A 28 B
16 A 50 C
82 C 34 B
15 C 4 B
88 A 42 B
90 A 13 A
17 B 21 A
32 B 18 B
22 C 53 B
81 B 67 B
71 A 48 A
73 C 47 B
21 A 34 B
83 C 60 B
40 A 78 C
22 C 7 A
79 C 55 C
40 A 46 C
58 A 79 C
87 A 99 A
92 C 55 C
20 B 75 B
72 C 41 A
28 B 52 B
60 B 50 C
51 A 32 B
96 B 24 B
18 B 31 B
83 C 59 A
24 B 74 A
88 A 97 B
81 B 67 B
51 A 72 C
64 C 8 A
51 A 50 C
7 A 42 B
4 B 78 C
68 B 27 A
70 A 95 C
30 B 29 C
96 B 81 B
13 A 44 B
4 B 82 C
74 A 38 B
92 C 49 A
12 C 79 C
46 C 44 B
97 B 96 B
15 C 60 B
56 C 65 A
61 B 14 A
58 A 16 A
43 B 26 B
42 B 12 C
72 C 24 B
41 A 68 B
4 B 5 C
63 B 59 A
86 C 88 A
48 A 77 C
36 B 59 A
7 A 33 A
2 C 56 C
81 B 69 A

输出样例#2:

CABABCCABBCBCABAACBCCBCCAACBCBAACCBAAABCCCACCAACACCBAAAACCBACAABCCCACCCABCAABBAACBBACBCBBBCBABBACACA

说明
【样例1解释】

小 L 计划进行 3 3 场游戏,其中第 1 场的地图类型是x,适合所有赛车,第 2 2 场和第 3 场的地图是c,不适合赛车C。

小 L 希望:若第 1 1 场游戏使用赛车A,则第 2 场游戏使用赛车B。那么为这 3 3 场游戏分别安排赛车A、B、A可以满足所有条件。若依次为 3 场游戏安排赛车为BBB或BAA时,也可以满足所有条件,也被视为正确答案。但依次安排赛车为AAB或ABC时,因为不能满足所有条件,所以不被视为正确答案。

题解

如果 d=0 d = 0 的话,就是 2SAT 2 − S A T 裸题。

如果 d>0 d > 0 的话,最暴力的想法是 O(3d) O ( 3 d ) 枚举所有情况,但是这样显然会 T T 。事实上,当地图为a时,只能用 B,C B , C ,当地图为 b b 时,只能用A,C,如果上述两种方案都不可行,那就只能用 C C 了。

综上,我们只需要枚举两种情况,复杂度为O(2d(n+m))

代码
#include<bits/stdc++.h>
using namespace std;
const int M=1e5+5;
struct sd{int a,b;char ha[2],hb[2];}lim[M];
int n,mx,d,m,cot,col,tot,df,top,pos[M][3],all[M],head[M],nxt[M<<1],to[M<<1],low[M],sta[M],dfn[M],bel[M];
bool vis[M];
char ch[M];
void tarjan(int v)
{
    dfn[v]=low[v]=++tot,vis[v]=1,sta[++top]=v;
    for(int i=head[v];i;i=nxt[i])
    {
        if(!dfn[to[i]])tarjan(to[i]),low[v]=min(low[to[i]],low[v]);
        else if(vis[to[i]])low[v]=min(low[v],dfn[to[i]]);
    }
    if(dfn[v]==low[v])
    {for(bel[v]=++col,vis[v]=0;sta[top]!=v;--top)bel[sta[top]]=col,vis[sta[top]]=0;--top;}
}
void add(int f,int t){nxt[++tot]=head[f],head[f]=tot,to[tot]=t;}
bool sat()
{
    memset(head,tot=col=0,sizeof(head));
    memset(dfn,df=0,sizeof(dfn));
    for(int i=1;i<=m;++i)
    {
        if(lim[i].ha[0]+32==ch[lim[i].a])continue;
        int ca=pos[lim[i].a][lim[i].ha[0]-'A'],cb=pos[lim[i].b][lim[i].hb[0]-'A'],a=lim[i].a<<1,b=lim[i].b<<1;
        if(lim[i].hb[0]+32==ch[lim[i].b])add(a+ca,a+ca^1);
        else add(a+ca,b+cb),add(b+cb^1,a+ca^1);
    }
    for(int i=2;i<=mx;++i)if(!dfn[i])tarjan(i);
    for(int i=2;i<=mx;i+=2)if(bel[i]==bel[i^1])return 0;
    for(int i=2;i<=mx;i+=2)
    {
        if(bel[i]<bel[i^1]){if(ch[i>>1]=='a')putchar('B');else putchar('A');}
        else{if(ch[i>>1]=='c')putchar('B');else putchar('C');}
    }
    return 1;
}
void dfs(int v)
{
    if(v>d){if(sat())exit(0);return;}
    ch[all[v]]='a',pos[all[v]][1]=0,pos[all[v]][2]=1;dfs(v+1);
    ch[all[v]]='b',pos[all[v]][0]=0,pos[all[v]][2]=1;dfs(v+1);
}
void in(){scanf("%d%d%s%d",&n,&d,ch+1,&m);for(int i=1;i<=m;++i)scanf("%d%s%d%s",&lim[i].a,lim[i].ha,&lim[i].b,&lim[i].hb);}
void ac()
{
    for(int i=1;i<=n;++i)if(ch[i]=='x')all[++cot]=i;else if(ch[i]=='a')pos[i][2]=1;else if(ch[i]=='b')pos[i][2]=1;else pos[i][1]=1;
    mx=n<<1|1,dfs(1);puts("-1");
}
int main(){in();ac();}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ShadyPi

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值