穷竭搜索: POJ 2718 Smallest Difference

题目http://poj.org/problem?id=2718

题意

就是输入N组数据,一组数据为,类似 【1  4  5  6  8  9】这样在0~9之间升序输入的数据,然后从这些数据中切一刀,比如  n1:【1 4 5】,n2:【6 8 9】这样,然后 abs(n1- n2),对n1 和 n2的所有可能的排列 n1: 【1 4 5】【1 5 4】...这样,要算出来的最小的差,显然从中间切一刀才会出现这种解。

题解

这里可以用来练习 STL,算法不会也没有关系,可以在这题学到 bitset 的用法,类模板 bitset 表示一个 N 位的固定大小序列。可以用标准逻辑运算符操作位集,并将它与字符串和整数相互转换。如:bitset<10> used = static_cast<bitset<10>>(permute),10个二进制位, permute表示这个数的二进制表示形式;比如:permute=3; used就是 0000000011; used[0] = used[1] = 1; 这个低位在右边 

我们这样,设输入字符串长度 len, 我们遍历 2 ^ len种可能,  used[i] == 1,则 s1 += line[i] ;否则 s2 += line[i];这样避免了  s1 = "1 4 5", s2 = "6 8 9" 或 s1 = "6 8 9", s2 = "1 4 5" 这种重复的情况。这样 s1, s2就被切割出来了。再对 s1, s2字符串的位置进行搜索, s1 = "123", "132"....这样 

AC代码:

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <string>
#include <cmath> 
#include <bitset>
using namespace std;

int T;
const int INF = 999999999;

void solve()
{
    scanf("%d", &T);
    getchar();        //下面输入 带空格的字符串, 需要吃掉输入T的回车,再可以
    while (T--)
    {
        string line;
        getline(cin, line);
        line.erase(remove(line.begin(), line.end(), ' '), line.end());      //擦除' '
        int ans = INF;
        int half = line.size() / 2;
        int len = line.size();
        int permute = 1 << len;    // 2 ^ len ; 
        
        do {
            //10个二进制位, permute表示这个数的二进制表示形式; permute=3; used就是 0000000011; 
            bitset<10> used = static_cast<bitset<10>>(permute);    // used[0] = used[1] = 1; 这个低位在右边 
//            cout << "Debug: " << used << endl;                     //可以输出used看看 
            string s1, s2;
            for (int i = 0; i < len; i++)
            {
                if (used[i])
                {
                    s1 += line[i]; 
                }
                else 
                {
                    s2 += line[i];
                }
            }
            if ((s1.size() != half) || (s1[0] == '0' && s1.size() > 1))
            { 
                continue;
            }
            //s1 s2已经被切割出来了
            //s1, s2字符串的位置进行搜索, s1 = "123", "132"....这样 
            do 
            {
                int n1 = atoi(s1.c_str());
                do {
                    if (s2[0] == '0' && s2.size() > 1) {
                        continue;
                    }
                    int n2 = atoi(s2.c_str());
                    int diff = abs(n1 - n2);
                    if (diff < ans) {
                        ans = diff;
                    }
                } while (next_permutation(s2.begin(), s2.end()));
            } while(next_permutation(s1.begin(), s1.end()));
        } while (--permute);
        
        printf("%d
", ans);
    }   
    
}

int main()
{
    solve();
    
    return 0;
}
原文地址:https://www.cnblogs.com/douzujun/p/8510914.html