• POJ2531 Network Saboteur 枚举||随机化


    题意:给定一个完全图,现在要求将这个图划分成两个部分,求两个部分的点做笛卡尔积之后的点对的距离和最大值是多少。

    解法一:由于给定的点最多只有20个,所以直接2^N*O(n)的时间复杂度枚举即可。

    解法二:采用随机化算法,枚举某一个点,将这个点所属于的集合进行翻滚。

    代码如下:

    #include <cstdlib>
    #include <cstring>
    #include <cstdio>
    #include <iostream>
    using namespace std;
    
    int N, G[25][25];
    
    int cal(int x) {
        int A[25], B[25], ca = 0, cb = 0, ret = 0;
        for (int i = 0; i < N; ++i) {
            if (x & (1 << i)) {
                A[ca++] = i + 1;
            } else {
                B[cb++] = i + 1;    
            }
        }
        for (int i = 0; i < ca; ++i) {
            for (int j = 0; j < cb; ++j) {
                ret += G[A[i]][B[j]];
            }    
        }
        return ret;
    }
    
    int main() {
        int ret;
        while (scanf("%d", &N) == 1) {
            ret = 0;
            for (int i = 1; i <= N; ++i) {
                for (int j = 1; j <= N; ++j) {
                    scanf("%d", &G[i][j]);
                }
            } // 对给定信息进行存储
            int mask = (1 << N) - 1;
            for (int i = 1; i < mask; ++i) {
                ret = max(ret, cal(i));
            }
            printf("%d\n", ret);
        }
        return 0;    
    }

    下面这个随机化代码G++过不了,不知道为什么。

    #include <cstdlib>
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <ctime>
    #include <map> 
    using namespace std;
    // 由于问题的规模相对较小
    // 可以使用随机化算法来解决这个问题 
    
    int N, G[30][30];
    
    int randtime = 200000;
    
    int A[30];
    
    void MoveAToB(int x, int &t) {
        A[x] = 0;
        for (int i = 1; i <= N; ++i) {
            if (A[i]) t += G[x][i];
            else t -= G[x][i];
        }
    }
    
    void MoveBToA(int x, int &t) {
        A[x] = 1;
        for (int i = 1; i <= N; ++i) {
            if (!A[i]) t += G[x][i];
            else t -= G[x][i];
        }    
    }
    
    int randpro() {
        int rd, ret = 0, t = 0;
        for (int i = 0; i < randtime; ++i) {
            rd = rand() % N + 1; // 得到一个点,这个点被
            if (A[rd]) { // 说明在A集合
                MoveAToB(rd, t);
            } else {  // 说明在B集合
                MoveBToA(rd, t);
            }
            ret = max(ret, t);
        }
        return ret;
    }
    
    int main() {
        srand(time(NULL));
        while (scanf("%d", &N) == 1) {
            for (int i = 1; i <= N; ++i) {
                for (int j = 1; j <= N; ++j) {
                    scanf("%d", &G[i][j]);
                }
            }
            for (int i = 1; i <= N; ++i) {
                A[i] = 1; 
                // 先假设所有的元素都是属于第一个集合
            }
            printf("%d\n", randpro());
        }    
        return 0;
    }

     

  • 相关阅读:
    阻塞队列整理
    List与Map整理
    2、Redis中的链表
    【观点】从曾成杰案看民间金融的高风险与银行缺失的机制创新
    林权抵押贷款政策出台 将实现林业资源变资本
    从《男生传递微笑给女生的故事》想到的流程梳理与优化
    落实制度靠流程<摘自平安50万人的执行力>
    vue踩坑- 报错npm ERR! cb() never called!
    vue踩坑-This dependency was not found
    vue踩坑- 报错npm ERR! cb() never called!
  • 原文地址:https://www.cnblogs.com/Lyush/p/2777998.html
Copyright © 2020-2023  润新知