Uva 140 Bandwidth

  基本思路是暴力枚举,思考一下可以发现,可以跳过一下情况。对于目前最小的minBW,每次枚举一种排列计算bandwidth进行比较,如果大于当前minBW已经可以断定这个排列已经不可能是最好的解了。

  而且对于一个点来说,与它相连的点为N,那么就这个点而言,最好情况就是这些点分布在其两侧,bandwidth为ceil(N / 2)

    举例:A:BCDEFG

    对于排列BCDAEFG可以发现其bandwidth为3

      而对后续的排列BCDEAFG来说,B与A的距离就为4,大于之前的最佳情况3了,已经没有必要继续蒜C和A的情况了。

 

  我采用了<algorithm>中的next_permutaiton()函数,帮忙枚举每一种排列。关于此函数,可参考Reference

 

  一点收获:就剪枝而言,考虑如何剪枝的时候,要考虑当前点最好的情况是什么,从而在这角度出发,如果某一点连最好的情况都达不到,那么这里就可以剪枝。 就比如这题的bandwidth,如果一个点在最好的情况都不能大于当前的最大值了,就没有必须继续搜索了,所以可以剪枝

  

#include <iostream>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <vector>

using namespace std;

const int MAXN = 26 + 5;
std::vector<int> permu, ans, link[MAXN];

void Link(string &s) {
    int isLink[MAXN][MAXN] = {false};
    size_t pos = 0;
    while(pos < s.size()) {
        int head = s[pos] - 'A';
        pos += 2; // jump over :
        while(pos < s.size() && s[pos] != ';') {
            isLink[head][s[pos] - 'A'] 
                = isLink[s[pos] - 'A'][head] = true;
            ++ pos;
        }
        ++ pos; // jump over ';'
    }
    for(int i=0; i<MAXN; ++ i) {
        link[i].clear();
        for(int j = 0; j < MAXN; ++ j) {
            if(isLink[i][j]) {
                link[i].push_back(j);
            }
        }
    }
}

int Abs(int s) {
    return s > 0 ? s : -s;
}

int minBW;
int GetBW() {
    int pos[MAXN];
    for(size_t i = 0; i < permu.size(); ++ i) {
        pos[permu[i]] = i;
    }
    int maxBW = -1;
    for(size_t i = 0; i < permu.size(); ++ i) {
        int tmp = -1;
        int order = permu[i];
        if( ceil(link[order].size() / 2.0) > minBW ) {
            return 1 << 10;
        }
        for(size_t j = 0; j < link[order].size(); ++ j) {
            int dis = Abs(pos[link[order][j]] - i);
            if(dis > minBW) {
                return 1 << 10;
            }
            tmp = tmp > dis ? tmp : dis;
        }
        maxBW = maxBW > tmp ? maxBW : tmp;
    }
    return maxBW;
}

int main() {
    ios::sync_with_stdio(false);
    string s;
    while(cin >> s && s != "#") {
        Link(s);
        permu.clear();
        for(int i=0; i<MAXN; ++ i) {
            if(link[i].size()) {
                permu.push_back(i);
            }
        }
        minBW = 1 << 10;
        do{
            int value = GetBW();
            if(minBW > value) {
                minBW = value;
                ans = permu;
            }
        }while(next_permutation(permu.begin(), permu.end()));
        for(size_t i = 0; i < ans.size(); ++ i) {
            cout << char(ans[i]+'A') << " ";
        }
        cout << "-> " << minBW << endl;
    }
    return 0;
}

 

posted @ 2015-08-06 21:00  Emerald  阅读(289)  评论(0编辑  收藏  举报