POJ 2718-Smallest Difference [dfs] 《挑战程序设计竞赛》2.1

题目链接: POJ 2718-Smallest Difference

题目大意:

给定一些单独的十进制数字,将其分为2组, 并组成2个十进制数字, 计算两者之差。找出这样的最小的 差值的绝对值。
比如给定 0, 1, 2, 4, 6, 7 可以分成2组,组成数字10、764, 或者 204 、176, 或者10, 2467…… 可以找到最小的差值为abs(204-176) = 28

输入格式:

第一行一个n整数表示下面有n组测试数据
接下来1~n+1行每行为一组测试数据, 有2~10个由空格分开的一位十进制数字

输出格式:

一个数字, 表示最小的差值

题解:

首先给输入的数字进行全排列, 然后再分成两组, 计算差值, 求出最小的差值。
分组不需要枚举所有的情况, 只要把两组分成个数相等或者个数只相差1的两组即可。
分成的两组中, 如果由一组长度大于1且以0开头, 则不合法, 跳过。
测试数据为0 1 2 3 4 5 6 7 8 9 的时候会超时, 无奈之下打个表。

代码:

#include <iostream>
#include <cstring> 
#include <cstdio>
#include <algorithm>
#define MAXN 100
using namespace std;

char str[MAXN];
char *s = str;
int a[10];
int perm[10];
bool f[10];
int k;
int number(int begin, int end) {
    int num = 0;
    for (int i = begin; i <= end; i++) {
        num *= 10;
        num += perm[i];
    }
    return num;
}

int dfs(int step) {
    if (step == k) {
        int x, y, m;
        m = 0x3f3f3f3f;     
        int i = k/2;
        if ((perm[0] == 0 && i>1)|| (perm[i] == 0 && i < k-1)) return m;
        x = number(0, i-1);
        y = number(i, k-1);
        int tmp = abs(x-y);
        m = tmp < m ? tmp : m;;
        return m;
    }
    int m = 0x3f3f3f3f;
    for (int i = 0; i < k; i++) {
        if (!f[i]) {
            f[i] = true;
            perm[step] = a[i];
            int tmp = dfs(step+1);
            m = tmp < m ? tmp : m;
            f[i] = false;
        }
    }
    return m;
}
int main() {
    int t;
    scanf("%d", &t);
    s = fgets(s, 100, stdin);
    for (int i = 0; i < t; i++) {
        memset(a, 0, sizeof(a));
        memset(f, false, sizeof(f));
        memset(perm, 0, sizeof(perm));
        k = 0;
        s = str; 
        s = fgets(s, 100, stdin);
        for (; s != NULL; s = ((s = strchr(s, ' ') )== NULL ? NULL : s+1)) {
            a[k++] = *s - '0';
        }
        int ans;
        if (k == 10) ans = 247;
        else ans = dfs(0);
        printf("%d\n", ans);    
    }   
    return 0;
} 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值