Time Limit:1000MS Memory Limit:65536KB 64bit IO Format:%I64d & %I64u
Description
For example, if you are given the digits 0, 1, 2, 4, 6 and 7, you can write the pair of integers 10 and 2467. Of course, there are many ways to form such pairs of integers: 210 and 764, 204 and 176, etc. The absolute value of the difference between the integers in the last pair is 28, and it turns out that no other pair formed by the rules above can achieve a smaller difference.
Input
Output
Sample Input
1
0 1 2 4 6 7
Sample Output
用暴力的dfs可以过,不过时间比较危险,(未剪枝,且未删除冗余情况)
//
// Create by 神舟 on 2015-02-22
//
#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <algorithm>
#include <cctype>
#include <stack>
#include <queue>
#include <map>
#include <string>
#include <set>
#include <vector>
using namespace std;
#define ll long long
const int inf=0x3f3f3f3f;
const int maxn=1e5+5;
const int MOD=5e5+5;
bool used[15];
void dfs(int step, int big, int small)
{
if(step == n){
if(big < small) swap(big, small);
if(l-r > big - small) l=big, r=small;
//printf("%d\t%d\n",big,small);
return;
}
if(step&1){
for(int i = 0; i < n; i++){
if(!used[i]){
if(num[i] == 0 && step == 1) continue;
used[i] = true;
dfs(step + 1, big * 10 + num[i], small);
used[i] = false;
}
}
}
else{
for(int i = 0; i < n; i++){
if(!used[i]){
if(num[i] == 0 && step == 0) continue;
used[i] = true;
dfs(step + 1, big, small * 10 + num[i]);
used[i] = false;
}
}
}
}
int main()
{
#ifdef LOCAL
freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
#endif
ios_base::sync_with_stdio(0);
while(t--){
n=0;
CLR(used);
CLR(num);
char tmp;
while(scanf("%c", &tmp)!=EOF && tmp != '\n'){
if(isdigit(tmp))
num[n++] = tmp - '0';
}
if(n == 2) l = num[1], r = num[0];
else{
l = inf, r = 0;
dfs(0, 0, 0);
}
printf("%d\n" , l - r);
}
return 0;
}
这个是完完全全的无脑dfs(虽然写的还是很艰难,看来对dfs理解不够)
还有一种 是用dfs枚举一半的情况,然后将另一半情况用排列 挨个试出最小差
核心代码如下:(粘贴别人的)
void solve(int aa) {
int m = 0;
for (int i = 0; i < n; ++ i) {
if (!used[i]) {
b[m++] = a[i];
}
}
do {
int bb = 0;
for (int i = 0; i < m; ++ i) {
bb = bb*10 + b[i];
}
if (b[0] != 0 || m == 1) {
ans = min(ans, abs(aa - bb));
}
}while(next_permutation(b, b + m));
}
void dfs(int k, int r) {
if (k == n/2) {
solve(r);
} else {
for (int i = 0; i < n; ++ i) {
if (!used[i]) {
if (a[i] == 0 && k == 0 && n > 3) continue;
used[i] = true;
dfs(k+1, r*10+a[i]);
used[i] = false;
}
}
}
}
接下来是 全排列 无dfs的做法 next_permutation 的写法就是求num数组的全排列 n为长度
//
// Create by 神舟 on 2015-02-22
//
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <algorithm>
#include <cctype>
#include <stack>
#include <queue>
#include <map>
#include <string>
#include <set>
#include <vector>
using namespace std;
#define CLR(x) memset(x,0,sizeof x)
#define ll long long
const int inf=0x3f3f3f3f;
const int maxn=1e5+5;
const int MOD=5e5+5;
int n, num[15];
int get(int l, int r)
{
int ret = 0;
for(int i = l; i < r; i++){
if(num[l] == 0) break;
ret = ret * 10 + num[i];
}
return (ret == 0 ? inf:ret);
}
int main()
{
#ifdef LOCAL
freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
#endif
ios_base::sync_with_stdio(0);
int t; scanf("%d ", &t);
while(t--){
char c;
int ans = inf;
n=0;
while(scanf("%c", & c) != EOF && c != '\n')
if(isdigit(c)){
num[n++] = c-'0';
}
if(n == 2) ans = num[1] - num[0];
else do{
int l = get(0, n>>1);
int r = get(n>>1, n);
//printf("%d %d \n",l,r);
//for(int i = 0; i < n; i++) printf("%d",num[i]);
//printf("\n");
if(l != inf && r != inf)
ans = min(ans, abs(l - r));
}while(next_permutation(num, num + n));
printf("%d\n", ans);
}
return 0;
}
我把n/2 写成了n>>2 ,坑了自己好久