四校联考2017.8.20T1填算式
Posted lazytear
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了四校联考2017.8.20T1填算式相关的知识,希望对你有一定的参考价值。
由于T2和T3都太高深了太巧妙了,于是只会做T1,拿了95分。现提供95分做法与满分做法
数据范围:n≤13,1≤ai≤9,0≤k≤109
大意:给n个数,在其中填+−×,允许多个数合并为一个。求使得最终结果等于k的算式数量。(这不就是我们平常玩的24点的加强版吗?)
95分解法:我们注意到对于第一个数字,其前面的操作只能为加法,对于之后的每一个数字,我们都有四种操作:在前面填加号,减号,乘号;与前面的数字合并。注意到n的值很小,于是考虑深搜。用两个数组分别记这个算式的符号和数字,当深搜到最后的时候check。深搜部分复杂度约为O(4n-1×n)。因此最后一个点会T。
95分代码如下:
1 include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<cstdlib> 5 #include<algorithm> 6 #include<cctype> 7 using namespace std; 8 int n,k; 9 long long x,ans=0; 10 int a[30]; 11 long long ex[30],opr[30]; 12 struct node{ 13 long long opr,num; 14 }sta[30]; 15 long long check(int tot){ 16 int top=0; 17 long long sum=0; 18 for(int i=1;i<=tot;++i){ 19 if(opr[i]!=3){ 20 sta[++top].num=ex[i]; 21 sta[top].opr=opr[i]; 22 } 23 else sta[top].num*=ex[i]; 24 } 25 while(top>0){ 26 if(sta[top].opr==1) sum+=sta[top].num; 27 else sum-=sta[top].num; 28 top--; 29 } 30 return sum; 31 } 32 void tryy(int i,int j){ 33 if(i>n){ 34 long long now=check(j); 35 if(now==k) ans++; 36 return ; 37 } 38 ex[j]=ex[j]*10+a[i]; 39 tryy(i+1,j); 40 ex[j]/=10; 41 ex[j+1]=a[i];opr[j+1]=1; 42 tryy(i+1,j+1); 43 opr[j+1]=2; 44 tryy(i+1,j+1); 45 opr[j+1]=3; 46 tryy(i+1,j+1); 47 } 48 int main(){ 49 freopen("expr.in","r",stdin); 50 freopen("expr.out","w",stdout); 51 scanf("%d%d",&n,&k); 52 int i,j; 53 for(i=1;i<=n;++i){ 54 scanf("%d",&a[i]); 55 } 56 ex[1]=a[1];opr[1]=1; 57 tryy(2,1); 58 printf("%d\\n",ans); 59 return 0; 60 }
满分做法:我们注意到复杂度为O(4n-1)完全可以过。因此我们只需要优化check部分即可。
我们考虑到这些算式中只有乘法具有优先级,一旦乘号后面出现加减号,这部分结果就对后面的运算不产生影响。因此我们在DFS的参数里面存储当前运算结果,一边DFS一边计算。记三个变量a,b,c。其中a代表的是当前加法算式的值,b代表的是当前这个数要乘上的倍数,c代表的是当前这一个数。初始 a=c=0,b=1。不填,则 c=10*c+x[i]。填+,则 a=a+b*c,b=1,c=x[i]。填-,则 a=a+b*c,b=-1,c=x[i]。填×,则 b=b*c,c=x[i]。最后 a+b*c就是运算结果。这样的话复杂度为O(4n-1)。可得100分。
满分代码如下:
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<cstdlib> 5 #include<algorithm> 6 #include<cctype> 7 #define ll long long 8 using namespace std; 9 int n,k; 10 long long ans=0; 11 ll x[30]; 12 long long ex[30],opr[30]; 13 void tryy(int i,ll a,ll b,ll c){ 14 if(i>n){ 15 if(a+b*c==k) ans++; 16 return ; 17 } 18 tryy(i+1,a,b,c*10+x[i]); 19 tryy(i+1,a+b*c,1,x[i]); 20 tryy(i+1,a+b*c,-1,x[i]); 21 tryy(i+1,a,b*c,x[i]); 22 } 23 int main(){ 24 freopen("expr.in","r",stdin); 25 freopen("expr.out","w",stdout); 26 scanf("%d%d",&n,&k); 27 int i,j; 28 for(i=1;i<=n;++i){ 29 scanf("%d",&x[i]); 30 } 31 tryy(2,0,1,x[1]); 32 printf("%d\\n",ans); 33 return 0; 34 }
以上是关于四校联考2017.8.20T1填算式的主要内容,如果未能解决你的问题,请参考以下文章