Smallest Difference

Description

Given a number of distinct decimal digits, you can form one integer by choosing a non-empty subset of these digits and writing them in some order. The remaining digits can be written down in some order to form a second integer. Unless the resulting integer is 0, the integer may not start with the digit 0.

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

The first line of input contains the number of cases
to follow. For each case, there is one line of input containing at least two but
no more than 10 decimal digits. (The decimal digits are 0, 1, ..., 9.) No digit
appears more than once in one line of the input. The digits will appear in
increasing order, separated by exactly one blank space.

Output

For each test case, write on a single line the
smallest absolute difference of two integers that can be written from the given
digits as described by the rules above.

Sample Input

1
0 1 2 4 6 7

Sample Output

28

Source

Rocky Mountain 2005

题意:给一升序集合 集合中元素范围为1~9  从中寻找两个不相交子集(每个数只能用一次) 求这两个子集组成两个整数的差最小值

这题要注意一个情况,除了组成的数只有0,否则都不能以0为开头,如01是不存在的, 它并不等于1。 如果输入012,那么答案是 10-2 = 8,并不是2-1(01) = 1。

分析:这道题数据量很小 可以用next_permutation 来枚举所有的情况 由于只是要找差最小 所以枚举完只需要把枚举的情况从前到后组成两个位数相等(偶数情况) 或者 位数差1(奇数情况)的数 然后相减取绝对值(避免先后问题),然后取这些情况的最小值即可。

next_permutation函数将按字母表顺序生成给定序列的下一个较大的序列,直到整个序列为减序为止,使用方法是next_permutation(begin(),end())。

代码中以一个地方写的很妙 可以排除所有首元素为0的情况:

while(a[0] ==0)
next_permutation(a,a+cnt);//第一个数不能为0

因为next_permutation函数不会重复生成已经生成过的序列

这样就先排除了所有首数字为0的情况

#include <stdio.h>
#include <string.h>
#include <iostream>
#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <set>
#include <map>
#include <cstring>
#include <math.h>
#include <stdlib.h>
#include <time.h>
using namespace std;
char aa[];
int a[];
int cnt, mid, ans;
int main()
{
int t;
scanf("%d", &t);
getchar();
while(t--)
{
cnt = ;
int t;
while((t = getchar()) != '\n')
{
if(t != ' ')
{
aa[cnt] = t;
cnt++;
}
} int mid = cnt/;
ans = 1e9;
if(cnt == )
{
printf("%d\n",aa[]-aa[]);
continue;
}
for(int i = ; i < cnt; i++)
{
a[i] = aa[i] - '';
}
while(a[] ==)
next_permutation(a,a+cnt);//第一个数不能为0
do
{
if(a[mid])
{
int t1=,t2=;
for(int i=;i<mid;++i)
t1=t1*+a[i];
for(int i=mid;i<cnt;++i)
t2=t2*+a[i];
ans=min(ans,abs(t1-t2));
} }while(next_permutation(a,a+cnt));
printf("%d\n",ans); }
}

Next_permutation

前面说过 这题数据量很小 可以用枚举来实现 复杂度为O(n²) 但如果数据量增大 枚举就行不通了 这时候可以使用贪心的思想来做这道题。

设t1为大数 t2为小数

如果是奇数的情况 那么因为t1的位数比t2多一位 那么t1最高位挑选最小的元素 t2最高位挑选次小的元素 然后t1依次挑选尽可能小的元素 t2依次挑选尽可能大的元素 组成的数t1-t2就是答案

如果是偶数的情况 那么就需要枚举一下每个相邻的位    t1的最高位挑选相邻位置中较大的元素 t2最高位挑选相邻位置较大的元素 然后t1依次挑选尽可能小的元素 t2挑选尽可能大的元素

#include <stdio.h>
#include <string.h>
#include <iostream>
#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <set>
#include <map>
#include <cstring>
#include <math.h>
#include <stdlib.h>
#include <time.h>
using namespace std;
char aa[];
int a[];
int cnt, mid;
int main()
{
//freopen("1.txt","r",stdin);
//freopen("2.txt","w",stdout);
int t;
scanf("%d", &t);
getchar();
while(t--)
{
cnt = ;
int t;
while((t = getchar()) != '\n')
{
if(t != ' ')
{
aa[cnt] = t;
cnt++;
}
} int mid = cnt/; // printf("%d\n",cnt);
if(cnt == )
{
printf("%d\n",aa[]-aa[]);
continue;
}
for(int i = ; i < cnt; i++)
{
a[i] = aa[i] - '';
}
if(cnt % == )//偶数情况
{
int t1,t2;//t1小数 t2大数
bool vis[];
memset(vis,,sizeof(vis));
int ans = 1e9; for(int i = ; i < cnt-;i++)
{
if(a[i] == ) continue;
t1 = a[i];
t2 = a[i+];
// printf("1 %d %d\n",t2, t1);
vis[i]=;vis[i+] = ;
int ti = ,pos = cnt - ;
while(ti < cnt/- && pos >= )
{
if(!vis[pos])
{
t1 = t1* + a[pos];
vis[pos] = ;
ti++;
}
pos--;
}
ti = ,pos = ;
while(ti < cnt/- && pos < cnt)
{
if(!vis[pos])
{
t2 = t2* + a[pos];
ti++;
vis[pos] = ;
}
pos++;
}
memset(vis,,sizeof(vis));
// printf("2 %d %d\n",t2, t1);
ans = min(ans,t2- t1);
} printf("%d\n",ans);
}
else//奇数情况
{
int t1 , t2;//t1为大数 t2 为小数
if(a[] != )
{
t1 = a[];
t2 = a[cnt-];
for(int i = ; i <= mid;i++)
{
if(i == ) continue;
t1 = t1* + a[i];
}
for(int i = cnt-; i > mid; i--)
{
t2 = t2* + a[i];
}
printf("%d\n",t1-t2);
}
else
{
t1 = a[];
t2 = a[cnt-];
for(int i = ; i <= mid;i++)
{
if(i == ) continue;
t1 = t1* + a[i];
}
for(int i = cnt-; i > mid; i--)
{
t2 = t2* + a[i];
}
printf("%d\n",t1-t2);
} } }
}

贪心

POJ 2718 Smallest Difference(贪心 or next_permutation暴力枚举)的更多相关文章

  1. POJ 2718 Smallest Difference(最小差)

     Smallest Difference(最小差) Time Limit: 1000MS    Memory Limit: 65536K Description - 题目描述 Given a numb ...

  2. poj 2718 Smallest Difference(暴力搜索+STL+DFS)

    Smallest Difference Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 6493   Accepted: 17 ...

  3. POJ 2718 Smallest Difference dfs枚举两个数差最小

    Smallest Difference Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 19528   Accepted: 5 ...

  4. 穷竭搜索: POJ 2718 Smallest Difference

    题目:http://poj.org/problem?id=2718 题意: 就是输入N组数据,一组数据为,类似 [1  4  5  6  8  9]这样在0~9之间升序输入的数据,然后从这些数据中切一 ...

  5. POJ 2718 Smallest Difference 枚举

    http://poj.org/problem?id=2718 题目大意: 给你一些数字(单个),不会重复出现且从小到大.他们可以组成两个各个位上的数字均不一样的数,如 0, 1, 2, 4, 6 ,7 ...

  6. POJ 2718 Smallest Difference【DFS】

    题意: 就是说给你一些数,然后要求你使用这些数字组成2个数,然后求他们的差值最小. 思路: 我用的双重DFS做的,速度还比较快,其中有一个很重要的剪枝,若当前搜索的第二个数后面全部补零与第一个数所产生 ...

  7. poj 2718 Smallest Difference(穷竭搜索dfs)

    Description Given a number of distinct , the integer may not start with the digit . For example, , , ...

  8. POJ - 2718 Smallest Difference(全排列)

    题意:将n个数字分成两组,两组分别组成一个数字,问两个数字的最小差值.要求,当组内数字个数多于1个时,组成的数字不允许有前导0.(2<=n<=10,每个数字范围是0~9) 分析: 1.枚举 ...

  9. POJ 2718 Smallest Difference(dfs,剪枝)

    枚举两个排列以及有那些数字,用dfs比较灵活. dfs1是枚举长度短小的那个数字,dfs2会枚举到比较大的数字,然后我们希望低位数字的差尽量大, 后面最优全是0,如果全是0都没有当前ans小的话就剪掉 ...

随机推荐

  1. Luogu P1396 营救【最小生成树/二分答案/最短路】 By celur925

    题目描述 “咚咚咚……”“查水表!”原来是查水表来了,现在哪里找这么热心上门的查表员啊!小明感动的热泪盈眶,开起了门…… 妈妈下班回家,街坊邻居说小明被一群陌生人强行押上了警车!妈妈丰富的经验告诉她小 ...

  2. Ubuntu An error occurred,please run Package Manager..

    转自https://blog.csdn.net/idealcitier/article/details/78294137 An error occurred,please run Package Ma ...

  3. docker 端口被占用问题解决

    启动容器A, A的端口映射是 80:8080 外部的25000端口映射到服务内部的8080端口:有时候将容器关闭,重新构建镜像及启动容器时会出现一些报错, 比如端口被占用的报错,但通过docker p ...

  4. 使用VS2015打包winform程序安装包简单方法(不需要InstallShield)

    转载自:   DGPLM博客 使用VS2015打包winform程序安装包简单方法(不需要InstallShield)

  5. C#委托的用法 在C#中我想在一个方法中调用另一个按钮的事件,怎样来实现?

    最开始我也不清楚,后来我是这样想了. 1.事件和委托不是一个概念,你如果是调用control的事件,可以直接在其对应的事件eventhandler上attach自己的事件方法就好了如:this.But ...

  6. spark yarn cluster模式下任务提交和计算流程分析

    spark可以运行在standalone,yarn,mesos等多种模式下,当前我们用的最普遍的是yarn模式,在yarn模式下又分为client和cluster.本文接下来将分析yarn clust ...

  7. thinkphp3.2.3连接sqlserver 2008 R2 数据库

    环境: 操作系统——win7 64位旗舰版 PHP——thinkphp 3.23 数据库——Microsoft SQL Server 2008 R2 需要用到的软件: 步骤: 1.搜索SQLSRV30 ...

  8. 移动web开发基础(一)——像素

    这篇文章要弄清楚2个问题:一.什么是逻辑像素和物理像素:二.这两者有什么关系. 对于问题一,先抛出两个概念.我们经常使用的px就是逻辑像素,是浏览器使用的抽象单位:物理像素又和dp/pt(设备无关像素 ...

  9. 三种将list转换为map的方法(传统方法、jdk8 Stream流、guava)

    三种将list转换为map的方法 - jackyrong - ITeye博客:http://jackyrong.iteye.com/blog/2158009

  10. P1372 又是毕业季I

    题目背景 “叮铃铃铃”,随着高考最后一科结考铃声的敲响,三年青春时光顿时凝固于此刻.毕业的欣喜怎敌那离别的不舍,憧憬着未来仍毋忘逝去的歌.1000多个日夜的欢笑和泪水,全凝聚在毕业晚会上,相信,这一定 ...