loj2305 noi2017 游戏

题目链接

思路

既然\(x\)的数量那么小,我们就可以先把每个\(x\)搜索一遍。

枚举x的时候不需要把\(a,b,c\)全枚举一遍,只要枚举其中的两个就可以枚举到当前位置选任何车的情况。

然后就变成了只有\('a','b','c'\)的序列。寻找满足题目要求的方案。

\(2-sat\)模型。

连边的时候注意一些技巧,否则\(if\)写到自闭。。

在\(UOJ\)上会被卡掉\(3\)分。实在懒得去卡常了233

代码

/*
* @Author: wxyww
* @Date:   2019-04-29 09:08:01
* @Last Modified time: 2019-04-30 14:32:38
*/
#include<cstdio>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<queue>
#include<vector>
#include<ctime>
using namespace std;
typedef long long ll;
const int N = 100010;
ll read() {
    ll x=0,f=1;char c=getchar();
    while(c<'0'||c>'9') {
        if(c=='-') f=-1;
        c=getchar();
    }
    while(c>='0'&&c<='9') {
        x=x*10+c-'0';
        c=getchar();
    }
    return x*f;
}
vector<int>e[N];
char a[N],tmp[N];
int n,D,m;
int opp[N];
#define add(x,y) e[x].push_back(y)
int val[N];

int tot,dfn[N],low[N],vis[N],sta[N],coljs,col[N],top;

void tarjan(int u) {
    int k = e[u].size();
    dfn[u] = low[u] = ++tot;
    sta[++top] = u;vis[u] = 1;
    for(int i = 0;i < k;++i) {
        int v = e[u][i];
        if(!dfn[v]) {
            tarjan(v);low[u] = min(low[u],low[v]);
        }
        else if(vis[v]) low[u] = min(low[u],low[v]);
    }
    if(dfn[u] == low[u]) {
        ++coljs;
        do {
            int x = sta[top--];
            col[x] = coljs;
            vis[x] = 0;
        }while(sta[top + 1] != u);
    }
}

int t1[N],t2[N];
char h1[N],h2[N];

int get_u(int x,char y) {
    if(a[x] == 'a') return y == 'B' ? x : x + n;
    return y == 'A' ? x : x + n;
}

#define ote(x) x > n ? x - n : x + n

void solve() {
    memset(dfn,0,sizeof(dfn));memset(low,0,sizeof(low));
    memset(col,0,sizeof(col));
    coljs = 0,tot = 0;top = 0;
    for(int i = 1;i <= n + n;++i) e[i].clear();
    for(int i = 1;i <= m;++i) {
        if(a[t1[i]] == h1[i] - 'A' + 'a') continue;
        int u = get_u(t1[i],h1[i]);
        if(a[t2[i]] == h2[i] - 'A' + 'a') {
            add(u,ote(u));
            continue;
        }
        int v = get_u(t2[i],h2[i]);
        add(u,v);add(ote(v),ote(u));
    }
    for(int i = 1;i <= n + n;++i) if(!dfn[i]) tarjan(i);

    for(int i = 1;i <= n;++i) if(col[i] == col[i + n]) return;

    for(int i = 1;i <= n;++i) {
        if(col[i] < col[i + n]) {
            if(a[i] == 'a') putchar('B');
            else putchar('A');
        }
        else {
            if(a[i] == 'c') putchar('B');
            else putchar('C');
        }
    }
    exit(0);
}

void dfs(int pos) {
    if(pos == n + 1) {
        solve();
        return;
    }
    if(tmp[pos] != 'x') dfs(pos + 1);
    else {
        a[pos] = 'a';
        dfs(pos + 1);
        a[pos] = 'b';
        dfs(pos + 1);
    }
}

int main() {
    // freopen("2305/game3.in","r",stdin);
    n = read(),D = read();
    scanf("%s",tmp + 1);
    memcpy(a + 1,tmp + 1,n);
    m = read();
    for(int i = 1;i <= m;++i) {
        t1[i] = read();h1[i] = getchar();while(h1[i] != 'A' && h1[i] != 'B' && h1[i] != 'C') h1[i] = getchar();
        t2[i] = read();h2[i] = getchar();while(h2[i] != 'A' && h2[i] != 'B' && h2[i] != 'C') h2[i] = getchar();
    }

    dfs(1);
    puts("-1");
    return 0;
}

原文地址:https://www.cnblogs.com/wxyww/p/loj2305.html

时间: 2024-10-28 14:49:09

loj2305 noi2017 游戏的相关文章

【BZOJ4945】[Noi2017]游戏 2-SAT

[BZOJ4945][Noi2017]游戏 题目描述 题解:2-SAT学艺不精啊! 这题一打眼看上去是个3-SAT?哎?3-SAT不是NPC吗?哎?这题x怎么只有8个?暴力走起! 因为x要么不是A要么不是B,所以直接2^8枚举所有x就行了.然后就变成了一个2-SAT问题.假设有两场游戏1,2,分别可以使用的地图为A1,A2,B1,B2,如果有一个限制是1 A 2 A,那么选A1就必须选A2,然后我这个沙茶就开开心心的拿了55分. 为什么不对?我建出来的图显然不对偶啊!考虑逆否命题,选A1就必须选

【uoj#317】[NOI2017]游戏 2-SAT

题目描述 给出 $n$ 个赛车赛道和A.B.C三种赛车,除了 $d$ 个赛道可以使用所有三种赛车以外每个都只能使用给出的两种之一.另外给出 $m$ 条限制:某个赛道使用X则某另一个赛道必须使用Y.问:是否存在一种方案满足所有条件?输出一种合法方案. $n]le 50000,d\le 8,m\le 100000$ . 题解 2-SAT 3-SAT是NP完全问题,由于 $d$ 只有 $8$ ,因此考虑枚举每个万能位置的取值,转化为2-SAT问题. 那么对于一条限制,显然描述对应着一条边:另外一个命题

【题解】NOI2017游戏

2-SAT.洛谷P3845 一开始以为--怎么有3个呢?后来发现因为每个地图都有一种车是不能用的,所以就等于每一个地图都有两个适应的车啦. 那么对于x类型的地图呢--只有8个,直接2^8暴力枚举每一种可能,就转化为了普通的问题. 令u,u'分别为一个地图适应的两种车,那么对于一个要求h1 - d1, h2 - d2而言,如果第一个既不是u,也不是u',说明可以无视:如果第二个都不能满足, 就连d1 - d1',表示如果必须选第一辆,问题无解.其余情况则d1-d2,d2'-d1'(重要!保证图的对

BZOJ4945 NOI2017 游戏 - 2-SAT

这题放在NOI里应该不算难的吧--但是细节比较多,所以写起来会有点** 题目限定了道路不能通行某种车辆,也就是可以通行两种车辆 我们将这两种车辆分别作为正点和反点进行约束就可以了 建图较为容易 最后将所有的x枚举一下即可 1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 #include <vector> 6 #inclu

[NOI2017]游戏

Sol 然而我的代码在\(UOJ\)上被\(hack\)\(\ TLE\)了 但思路是没问题的\(TAT\) 如果没有\(x\),就是个\(2-SAT\) 我们爆搜\(x\)的地图是\(a\)还是\(b\)就好了 不用枚举它是\(c\),枚举\(a\),\(b\)就能保证正好选\(ABC\)三种车 我也不知道我的输出方案哪里学的 拓扑排序+染色\(QAQ\) 如果觉得自己的代码优秀就去\(UOJ\)上交吧(逃 # include <bits/stdc++.h> # define RG regi

Luogu P4782 【模板】2-SAT 问题(2-SAT)

P4782 [模板]2-SAT 问题 题意 题目背景 \(2-SAT\)问题模板 题目描述 有\(n\)个布尔变量\(x_1\sim x_n\),另有\(m\)个需要满足的条件,每个条件的形式都是"\(x_i\)为\(true/false\)或\(x_j\)为\(true/false\)".比如"\(x_1\)为真或\(x_3\)为假"."\(x_7\)为假或\(x_2\)为假".\(2-SAT\)问题的目标是给每个变量赋值使得所有条件得到满足.

【NOI2017】游戏 2-sat算法

[题目]LibreOJ [题意]n场游戏,有三种车ABC,给定长度为n的字符串,'a'表示不能选A,'b''c'同理,'x'表示不限,至多d个'x'.有m个限制(i,hi,j,hj)表示如果第i场选择车hi,那么第j场必须选择车hj.求可行方案,或无解.n<=10^5,d<=8. [算法]2-sat [题解] 原文地址:https://www.cnblogs.com/onioncyc/p/8605676.html

20170913自制猜数字游戏

/* 猜数字:系统随机生成一个四位数,请根据下列判断猜出来 A:数值正确,位置正确 B:数值正确,位置不正确 C:数值不正确 */ #include<stdio.h> #include<time.h> #include<stdlib.h> #pragma warning (disable:4996) #define pUCharHead unsigned char * //以数组形式返回n个无重复的随机数,范围可指定[min,max] pUCharHead GenNoR

洛谷P1199 三国游戏

题目描述 小涵很喜欢电脑游戏,这些天他正在玩一个叫做<三国>的游戏. 在游戏中,小涵和计算机各执一方,组建各自的军队进行对战.游戏中共有 N 位武将(N为偶数且不小于 4),任意两个武将之间有一个"默契值",表示若此两位武将作为一对组合作战时,该组合的威力有多大.游戏开始前,所有武将都是自由的(称为自由武将,一旦某个自由武将被选中作为某方军队的一员,那么他就不再是自由武将了),换句话说,所谓的自由武将不属于任何一方. 游戏开始,小涵和计算机要从自由武将中挑选武将组成自己的军