【NOIP模拟赛(六)】狐狸的谜语(puzzle) - 深度优先搜索 - 剪枝优化

Problem Puzzle

题目大意

给一个串s和数T,求最少插入多少个乘号或加号可以使答案为T。

Solution

因为数据较小,然后我们直接深度优先搜索。

但是我们需要加上四个剪枝。

  • 若当前已经搜索完毕的算式总和大于T则停止
  • 若当前加入的符号大于目前最小符号则停止
  • 若当前累加的数乘上前一个数已经大于T且串后面没有0可以抵消了则停止
  • 若当前进行插入乘号或加号都不符合前两条剪枝则停止该位dfs

虽然说得奇奇怪怪,看看代码就清楚了。

AC Code

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #define INF 2147483647
 5 using namespace std;
 6 typedef long long ll;
 7 int n,T,ans,zero;
 8 char s[25];
 9 bool dfs(int x,ll sum,ll now,int dep){
10     if(sum+(x>zero)*now>T||dep>ans)return 1;
11     if(x==n+1){
12         sum+=now;
13         if(sum==T)ans=min(ans,dep-1);
14         return 0;
15     }
16     ll tmp=0;
17     for(int i=x;i<=n;i++){
18         tmp=tmp*10+s[i]-'0';
19         int cheat=0;
20         if(dfs(i+1,sum+now,tmp,dep+1))++cheat;
21         if(x!=1)
22             if(dfs(i+1,sum,min(tmp*now,(ll)T+1LL),dep+1))
23                 ++cheat;
24         if(cheat==2)break;
25     }
26     return 0;
27 }           
28 int main(){
29     //freopen("a.in","r",stdin);
30     while(scanf("%s%d",s+1,&T)&&T>=0){
31         n=strlen(s+1);ans=INF;
32         zero=n+1;
33         ans=INF;
34         while(zero>=1&&s[zero]!='0')zero--;
35         dfs(1,0,0,0);
36         if(ans!=INF)printf("%d\n",ans);
37         else puts("-1");
38     }
39 }

 

posted @ 2017-09-20 22:23  skylynf  阅读(857)  评论(0编辑  收藏  举报