【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 }