POJ2718---Smallest Difference

题目大意:输入一串数字, 将其分为两组,每组随机搭配,组成一个整数,整数的不能以0开头,除非只有个位,求两个整数差的最小值
分析:DFS暴搜掉。很容易想到一个整数的位数为n/2,另一个为n-n/2时,差最小,所以,用next_permutation枚举。特殊情况需要注意,只有两个数字且其中一个为0,没注意这个,贡献了两个WA,晕死

代码:

#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;

int a[15], vis[15], n, ans, aa, bb;

void solve(int aa) {
    int len = 0, flag = 1, b[15];
    bb = 0;
    for(int i = 0; i < n; i++)
        if(!vis[i]) b[len++] = a[i];
    for(int i = 0; i < len; i++) {
        if(i == 0 && b[i] == 0) flag = 0;
        bb = bb * 10 + b[i];
    }
    if(flag) ans = min(ans, abs(aa-bb));
    while(next_permutation(b, b+len)) {         //next_permutation包含在algorithm中
        bb = 0;
        flag = 1;
        for(int i = 0; i < len; i++) {
            if(i == 0 && b[i] == 0) flag = 0;
            bb = bb * 10 + b[i];
        }
        if(flag) ans = min(ans, abs(aa-bb));
    }
    return;
}

void dfs(int k, int res) {
    if(k == n/2) {
        solve(res);
        return;
    }
    for(int i = 0; i < n; i++) {
        if(!vis[i]) {
            if(a[i] == 0 && k == 0) continue;
            vis[i] = 1;
            dfs(k+1, res*10+a[i]);
            vis[i] = 0;
        }
    }
    return;
}

int main() {
    int kase;
    scanf("%d", &kase);
    getchar();
    while(kase--) {
        n = 0;
        char ch;
        memset(a, 0, sizeof(a));
        memset(vis, 0, sizeof(vis));
        while((ch = getchar()) != '\n') {
            if(ch == ' ')
                continue;
            else a[n++] = ch - '0';
        }
        if(n == 2 && a[0] == 0) {               //当只有两个数字,且其中一个为0时,特殊处理
            printf("%d\n", a[1]-a[0]);
            continue;
        }
        ans = 1 << 30;
        dfs(0, 0);
        printf("%d\n", ans);
    }
    return 0;
}

你可能感兴趣的:(poj)