您的位置:首页 > Web前端

POJ_2718_The smallest difference_DFS,剪枝

2014-11-16 21:00 190 查看
好好努力,上海加油。

题意:

给最少2个,最多10个数字,要求由这些数字拼起来组成两个数,没有前缀零,问所有合法组成的两个数中,差值最小是多少?

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.

两个数尽量等长差值肯定相对较小,所以就遍历n!种排列方式,从中间分开,算差值,更新答案。

算下操作数没多少,10!才3*10^6级别,但是还是超时了。

剪枝:当当前组成的第二个数(此时还没组完),即使最大且比第一个数小时,差值仍然大于已有答案;

或当前组成的第二个数(此时还没组完),即使最小且比第一个数大时,差值仍然大于已有答案。

这两种情况不必继续搜索。

代码如下:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<cmath>
using namespace std;
#define mxl 30
#define mxn 20
#define inf 0x3f3f3f3f
int a[mxn],cnt;
int ans;
int poww[]={1,10,100,1000,10000};
bool isdigit(char in){
return in>='0'&&in<='9';
}
int iabs(int in){
return in<0 ? -in : in;
}
void dfs(int loc,int numa,int numb,int flag){
int tema,temb;
if(loc==cnt)
ans=min(ans,iabs(numa-numb));
if(loc-1>=cnt/2){
tema=numb*poww[cnt-loc];
temb=(numb+1)*poww[cnt-loc]-1;
if(tema>=numa&&tema-numa>=ans)	return;
if(temb<=numa&&numa-temb>=ans)	return;
}
for(int i=0;i<cnt;++i)	if(!(flag&(1<<i))){
if(!loc&&cnt>3&&!a[i])	continue;
if(loc==cnt/2&&cnt!=2&&!a[i])	continue;
tema=numa,temb=numb;
if(loc>=cnt/2)	temb=temb*10+a[i];
else	tema=tema*10+a[i];
dfs(loc+1,tema,temb,flag|(1<<i));
}
}
int main(){
int cs;
scanf("%d",&cs);
getchar();
while(cs--){
ans=inf;
cnt=0;
char eat;
while((eat=getchar())!='\n')	if(isdigit(eat))
a[cnt++]=eat-'0';
dfs(0,0,0,0);
printf("%d\n",ans);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: