zoukankan      html  css  js  c++  java
  • 洛谷P2962 [USACO09NOV]Lights G 题解 折半搜索/枚举

    之前的折半枚举的代码有一点点问题,已修改。 - 2020.10.3

    题目链接:https://www.luogu.com.cn/problem/P2962

    题目大意:

    (n(1 le n le 35)) 盏灯,每盏灯与若干盏灯相连,每盏灯上都有一个开关,如果按下一盏灯上的开关,这盏灯以及与之相连的所有灯的开关状态都会改变。一开始所有灯都是关着的,你需要将所有灯打开,求最小的按开关次数。

    解题思路:

    http://oi-wiki.com/search/bidirectional/

    基于这种思想,通过两次搜索把前一半和后一半的状态都枚举出来然后进行匹配。

    但是我这里是基于状态压缩的思想将所有状态用循环枚举出来的。

    示例代码:

    #include <bits/stdc++.h>
    using namespace std;
    const int maxn = 36, maxm = 1200;
    map<long long, int> mp;
    struct Edge {
        int v, nxt;
        Edge() {};
        Edge(int _v, int _nxt) { v = _v; nxt = _nxt; }
    } edge[maxm];
    int n, m, head[maxn], ecnt, ans = INT_MAX;
    void init() {
        ecnt = 0;
        memset(head, -1, sizeof(int)*(n+1));
    }
    void addedge(int u, int v) {
        edge[ecnt] = Edge(v, head[u]); head[u] = ecnt ++;
        edge[ecnt] = Edge(u, head[v]); head[v] = ecnt ++;
    }
    int main() {
        scanf("%d%d", &n, &m);
        init();
        while (m --) {
            int a, b;
            scanf("%d%d", &a, &b);
            addedge(a, b);
        }
        for (long long s = 0; s < (1<<(n/2)); s ++) {
            long long st = 0;
            for (int u = 1; u <= n/2; u ++) {
                if ((1<<(u-1)) & s) {
                    st ^= (1LL<<(u-1));
                    for (int i = head[u]; i != -1; i = edge[i].nxt) {
                        int v = edge[i].v;
                        st ^= (1LL<<(v-1));
                    }
                }
            }
            long long st2 = 0;
            for (int i = 0; i < n; i ++) if (!(st & (1LL<<i))) st2 ^= (1LL<<i);
            if (mp.find(st2) == mp.end()) mp[st2] = __builtin_popcount(s);
            else mp[st2] = min(mp[st2], __builtin_popcount(s));
        }
        for (long long s = 0; s < (1<<(n-n/2)); s ++) {
            long long st = 0;
            for (int u = n/2+1; u <= n; u ++) {
                if ((1<<(u-n/2-1)) & s) {
                    st ^= (1LL<<(u-1));
                    for (int i = head[u]; i != -1; i = edge[i].nxt) {
                        int v = edge[i].v;
                        st ^= (1LL<<(v-1));
                    }
                }
            }
            if (mp.find(st) != mp.end()) ans = min(ans, mp[st] + __builtin_popcount(s));
        }
        printf("%d
    ", ans);
        return 0;
    }
    

    折半搜索代码:

    #include <bits/stdc++.h>
    using namespace std;
    const int maxn = 36;
    map<long long, int> mp;
    vector<int> g[maxn];
    bool color[maxn];
    int n, m, ans = -1;
    void paint(int u) {
        color[u] = !color[u];
        int sz = g[u].size();
        for (int i = 0; i < sz; i ++) {
            int v = g[u][i];
            color[v] = !color[v];
        }
    }
    void dfs1(int u, int cnt) {
        if (u > n/2) {
            long long st = 0;
            for (int i = 1; i <= n; i ++) {
                if (!color[i]) st ^= (1LL<<(i-1));
            }
            if (mp.find(st) != mp.end()) {
                mp[st] = min(mp[st], cnt);
            }
            else mp[st] = cnt;
            return;
        }
        dfs1(u+1, cnt);
        paint(u);
        dfs1(u+1, cnt+1);
        paint(u);
    }
    void dfs2(int u, int cnt) {
        if (u > n) {
            long long st = 0;
            for (int i = 1; i <= n; i ++) {
                if (color[i]) {
                    st ^= (1LL<<(i-1));
                }
            }
            if (mp.find(st) != mp.end()) {
                int tmp = mp[st] + cnt;
                if (ans == -1 || ans > tmp) ans = tmp;
            }
            return;
        }
        dfs2(u+1, cnt);
        paint(u);
        dfs2(u+1, cnt+1);
        paint(u);
    }
    int main() {
        cin >> n >> m;
        while (m --) {
            int a, b;
            cin >> a >> b;
            g[a].push_back(b);
            g[b].push_back(a);
        }
        dfs1(1, 0);
        dfs2(n/2+1, 0);
        cout << ans << endl;
        return 0;
    }
    
    
  • 相关阅读:
    Windows Phone7官方更新 增加复制粘贴
    使Apache(Linux)支持Silverlight
    WPF触摸屏项目案例(放置在奔驰公司触摸屏展厅)
    项目开发项目管理(转)
    诺基亚WP7手机界面曝光
    Windows 8十大传言:令苹果坐立不安
    如何为 iPad 打造速度超快的 HTML5 软件
    Silverlight5.0正式发布附下载地址
    我们的案例请访问我们团队官网http://Silverlighter.net
    【转】NTFS3G的安装和配置
  • 原文地址:https://www.cnblogs.com/quanjun/p/13685993.html
Copyright © 2011-2022 走看看