四校联考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填算式的主要内容,如果未能解决你的问题,请参考以下文章

Tree (四校联考T1)

四校联考——20170730模拟赛

四校联考比赛题解FJ NOIP 四校联考 2017 Round 7

[20180901]四校联考

2017-2-19四校联考

[20180819]四校联考