A very hard Aoshu problem
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4403
DFS
这几天集训,一天也就写个4题,被虐哭QAQ。回寝室后游少说解搜索就大胆搜,最后剪个枝就好了Orz,然后我就尝试解这题(剪枝要风骚)。我先枚举等号的位置equ,然后搜索加号add的位置,然后主要的剪枝:如果等号左边运算后小于等号右边各个位上的数的和,那么后面的肯定不满足条件,右边同理。最后要小心爆int,这里吃了很多WA
代码如下:
1 #include<cstdio> 2 #include<cstring> 3 #define LL long long 4 using namespace std; 5 char str[16]; 6 LL pre[16]; 7 bool add[16]; 8 LL sum; 9 LL len; 10 LL equ; 11 void dfs(int index); 12 LL left(); 13 LL right(); 14 int main(void){ 15 //freopen("in.txt","r",stdin); 16 //freopen("out_1.txt","w",stdout); 17 scanf("%s",str); 18 while(strcmp(str,"END")){ 19 len=strlen(str); 20 memset(pre,0,sizeof(pre)); 21 pre[0]=str[0]-'0'; 22 for(int i=1;i<len;++i) 23 pre[i]=pre[i-1]+str[i]-'0'; 24 sum=0; 25 for(equ=1;equ<len;++equ){ 26 memset(add,0,sizeof(add)); 27 dfs(1); 28 } 29 printf("%I64d ",sum); 30 scanf("%s",str); 31 } 32 } 33 LL left(){ 34 LL s=0; 35 LL t=0; 36 for(LL i=0;i!=equ;++i){ 37 if(!add[i]){ 38 t=t*10+str[i]-'0'; 39 }else{ 40 s+=t; 41 t=str[i]-'0'; 42 } 43 } 44 s+=t; 45 return s; 46 } 47 LL right(){ 48 LL s=0; 49 LL t=0; 50 for(LL i=equ;i<len;++i){ 51 if(!add[i]){ 52 t=t*10+str[i]-'0'; 53 }else{ 54 s+=t; 55 t=str[i]-'0'; 56 } 57 } 58 s+=t; 59 return s; 60 } 61 void dfs(int index){ 62 LL l=left(); 63 LL r=right(); 64 if(l==r){ 65 sum++; 66 }else{ //剪枝 67 if(l<pre[len-1]-pre[equ-1]) 68 return; 69 if(r<pre[equ-1]) 70 return; 71 } 72 if(index>=len) 73 return; 74 for(LL i=index;i<len;++i){ 75 if(i!=equ){ 76 add[i]=1; 77 dfs(i+1); 78 add[i]=0; 79 } 80 } 81 }