zoukankan      html  css  js  c++  java
  • 四校联考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 }
  • 相关阅读:
    libmegjb.so加载问题调试和分析
    art虚拟机启动问题分析
    高通发布骁龙808六核/810八核64位芯片
    pivotx的entry和page内容里的日期格式修改
    dlmalloc(Android bionic C库的malloc实现)简介
    dojo分析之declare接口
    零基础搞懂智能机之手机参数怎么看
    Google one联合联发科,国内低端智能机方案怎么办?
    自己搭建云存储(WIFI路由器上接硬盘)
    数据结构目录(浙大)
  • 原文地址:https://www.cnblogs.com/lazytear/p/7468115.html
Copyright © 2011-2022 走看看