UVA140 Bandwidth(DFS+ 剪枝 + 回溯)

题目大意

给出一个图, 哪两个点相连, 问怎么排序使得相连点的间距最大值最小。

思路

很容易想到的思路就是dfs遍历解答树。但这样会超时,正确的做法是遍历的过程中进行剪枝

代码

// AC
#include <iostream>
#include <cstdio>
#include <cstring>
#include <climits>
#include <cmath>
#include <algorithm>
using namespace std;

bool road[30][30];
bool v[30];
int A[30];
int ans;
int dis;
int n;
int e[30];

void dfs(int cur) {
    int dis = 0;
    if (n == cur) {
        for(int i = 0; i < n - 1; i++) {
            for(int j = i + 1; j < n; j++) {
                if (road[A[i]][A[j]]) {
                    dis = max(j - i, dis);
                }
            }
        }
        if (dis < ans) {
            ans = dis;
            for(int i = 0; i < n; i++) {
                e[i] = A[i];            // e是用来保存最终结果的。
            }
        }
        return;
    }
    for(int i = 0; i < 26; i++) {
        if (v[i]) {
            int ok = 1;
            for(int j = 0; j < cur; j++) {
                if (road[A[j]][i]) {
                    if (cur - j > ans) {     // 剪枝, 如果间距大于以确定的最优解立刻甩掉这一条支路,这就是剪枝的含义。
                        ok = 0;
                        break;
                    }
                }
            }
            if (ok) {
                A[cur] = i;
                v[i] = false;
                dfs(cur+1);
                v[i] = true;
            }
        }
    }
}

int main()
{
   // freopen("input.txt", "r", stdin);
    char s[100];
    while(scanf("%s", s) && s[0] != '#')
    {
        memset(road, false, sizeof(road));
        memset(v, false, sizeof(v));
        ans = INT_MAX;
        dis = INT_MIN;
        n = 0;
        int flag = 1;
        char u;
        for(int i = 0; i < strlen(s); i++) {
            if (flag) {
                u = s[i];
                if (!v[u-'A']) {
                    v[u-'A'] = true;
                    n++;
                }
                flag = 0;
            }
            else if (s[i] == ';') {
                flag = 1;
            }
            else if (s[i] == ':') {
                continue;
            }
            else {
                road[u-'A'][s[i]-'A'] = road[s[i]-'A'][u-'A'] = true;
                if (!v[s[i]-'A']) {
                    v[s[i]-'A'] = true;
                    n++;
                }
            }
        }
        dfs(0);
        for(int i = 0; i < n; i++) {
            printf("%c ", e[i] + 'A');
        }
        printf("-> %d\n", ans);

    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/sunmaoxiang/article/details/80874876