zoukankan      html  css  js  c++  java
  • P2962 [USACO09NOV]灯Lights [高斯消元+异或方程组 / 折半搜索]

    LightsLights

    节日宴会上,我们有 N(10<=N<=36)盏彩色灯,他们分别从 1 到 N 被标上号码。有 M 条边连接着这些灯,当按下某一盏灯的开关的时候,这盏灯本身以及所有和这盏灯有边相连的灯的开关状态都会发生改变。最开始所有灯都是被关着的,问需要至少按下多少开关,才可以把所有灯打开。

    1N361 le N le 36.


    color{red}{正解部分}

    1:方法 1:
    这道题目 建立异或方程组, 对自由元的状态进行枚举, 解出方程, 从中选出最优解.

    2:方法 2:
    折半搜索,

    将原来的序列分为 N/2N/2NN/2N - N/2 两部分,

    始状态 搜出操作前半部分能得到的所有状态, 记为 S1S_1,
    末状态 倒搜出操作后半部分能得到的所有状态, 记为 S2S_2,

    S2S_2 中查找每个 S1S_1 中的元素, 找到则更新答案 .


    color{red}{实现部分}

    1:方法 1:

    .color{red}{待填坑 .}

    2:方法 2:

    注意 DFS_1DFS\_1DFS_2DFS\_2 不要搞混 .
    code with bug

    使用状态压缩:

    • 每个操作都可以使用二进制状态表示, 使用时直接对状态异或就可以方便地改变状态.
    • 使用 mapmap 保存状态.
    • 注意自环 .
    #include<bits/stdc++.h>
    #define reg register
    typedef long long ll;
    
    const int maxn = 300005;
    
    int N;
    int M;
    int Ans;
    
    ll Opt[maxn];
    
    std::map <ll, int> Mp;
    
    void DFS(int k, int cnt, ll zt){
            if(k == N+1){
                    if(Mp.count(zt)) Ans = std::min(Ans, cnt + Mp[zt]);
                    return ;
            }
            DFS(k+1, cnt+1, zt^Opt[k]), DFS(k+1, cnt, zt);
    }
    
    int main(){
            scanf("%d%d", &N, &M);
            for(reg int i = 1; i <= M; i ++){
                    int a, b;
                    scanf("%d%d", &a, &b);
                    Opt[a] |= (1ll<<b-1), Opt[b] |= (1ll<<a-1);
            }
            for(reg int i = 1; i <= N; i ++) Opt[i] |= (1ll<<i-1);
            int Half = N >> 1;
            for(reg int i = 0; i < 1<<Half; i ++){
                    int cnt = 0;
                    ll zt = 0;
                    for(reg int j = 1; j <= Half; j ++)
                            if((1ll<<j-1) & i) cnt ++, zt ^= Opt[j];
                    if(Mp.count(zt)) Mp[zt] = std::min(Mp[zt], cnt);
                    else Mp[zt] = cnt;
            }
            Ans = 0x3f3f3f3f;
            DFS(Half+1, 0, (1ll<<N)-1);
            printf("%d
    ", Ans);
            return 0;
    }
    
  • 相关阅读:
    试题 历届试题 整数拼接(数位dp)
    试题 历届试题 波动数列(dp)
    序列化二叉树(模拟)
    对于maven中无法加载类路径下的配置文件
    [蓝桥杯][算法训练]文章翻转
    [蓝桥杯][算法训练] 无权最长链
    [蓝桥杯][基础训练]2n皇后问题
    蓝桥杯 基础练习——Huffuman树
    蓝桥杯 基础练习——高精度加法
    蓝桥杯 基础练习——阶乘计算
  • 原文地址:https://www.cnblogs.com/zbr162/p/11822548.html
Copyright © 2011-2022 走看看