zoukankan      html  css  js  c++  java
  • NOIP2017 D1T2 时间复杂度

    洛谷P3952

    这一道模拟题是真的特别考细心的一道题……调了半天才调出来……要是今年noip考到这样的模拟题我可能就凉凉

    看到洛谷题解上有人用栈、递归,还有说离线判断的,我就在线外加各种条件就写出来了啊……正好100行

    思路:

    设变量ci[i]表示第i层的时间复杂度是O(n^ci[i])

    对于每次进入一个循环('F'),我们考虑这么几种情况:

    1、此层循环不会执行(外层循环x>y)

      只需判断此层循环是否有语法错误(变量重复)即可

    2、此层循环会执行,需要判断此层循环是否有语法错误(变量重复)并计算时间复杂度

      读入后先判断是否有语法错误(变量重复),并记录此变量

      ①可以进入此层循环(x<=y)

        若x为正整数,y为n,此层循环的时间复杂度=上一层时间复杂度+1;否则此层循环时间复杂度=上一层时间复杂度

      ②不能进入此层循环(x>y)

        做标记,并记录位置(便于删除标记)

    对于每次退出一个循环('E'):

    1、删除变量

    2、若此循环x>y(此前做的标记),则删除标记

    几个实现细节:

    Q:如何记录变量并判断变量是否重复?

    A:用tot和alpha[]记录循环层数及其变量名称,再用利用哈希的思想用数组hash[i]表示字母i在外层循环是否出现过,哈希函数也很简单,直接用ASCII码做哈希函数,访问是直接hash['字母']即可

    Q:如何判断x,y的大小?

    A:不能用string重载的运算符!string重载的运算符比较方法是从前向后逐个比较……和我们的需求不一样。可以写一个dayu()函数(博主英语不好),注意x,y为n的情况,然后判断x,y的长度,最后再逐个比较。还有一些比较巧妙的实现细节读者在代码里感受一下。

    代码:

      1 #include<iostream>
      2 #include<string>
      3 #include<algorithm>
      4 #include<cstring>
      5 using namespace std;
      6 bool hash[128];//判断字符是否使用过 
      7 char alpha[101];//存储使用过的字母 
      8 int ci[101];//每一层的时间复杂度 
      9 bool pd(int ans,string fuzadu)//判断时间复杂度为n^w是是否正确 
     10 {
     11     int length=fuzadu.length();
     12     bool pd=true;
     13     for(int i=length-2;i>=4;i--)
     14     {
     15         if(fuzadu[i]-'0'!=ans%10)
     16             pd=false;
     17         ans/=10;
     18     }
     19     return pd;
     20 }
     21 bool dayu(string x,string y)//上面已经判断过x为数字,y为n的情况,故此处不用判断 
     22 {
     23     if(x=="n"&&y!="n")
     24         return 1;
     25     if(x.length()>y.length())
     26         return 1;
     27     if(x.length()<y.length())
     28         return 0;
     29     for(int i=0;i<x.length();i++)
     30     {
     31         if(x[i]>y[i])
     32             return 1;
     33         if(x[i]<y[i])
     34             return 0;
     35     }
     36     return 0;
     37 }
     38 int main()
     39 {
     40     int t;
     41     cin>>t;
     42     while(t--)
     43     {
     44         memset(alpha,0,101);
     45         memset(ci,0,101);//初始化ci[]数组 
     46         memset(hash,false,128);//初始化哈希表 
     47         int l,ans=0,ceng=0,place=0;//最终答案;循环层数;未进行的循环的层数标记 
     48         string fuzadu;//输入复杂度字符串 
     49         bool not_do=false,wrong=false;//此层是否执行;是否有语法错误 
     50         cin>>l>>fuzadu;
     51         while(l--)
     52         {
     53             char ord;//进入循环或退出循环 
     54             cin>>ord;
     55             if(ord=='F')//进入循环 
     56             {
     57                 char i;
     58                 string x,y;
     59                 cin>>i>>x>>y;
     60                 if(hash[i])//判断是否有语法错误 
     61                     wrong=true;
     62                 else//若没有语法错误,存储该字符并做标记 
     63                 {
     64                     alpha[++ceng]=i;
     65                     hash[i]=true;
     66                 }
     67                 if(!not_do)//此层循环执行,计算时间复杂度 
     68                 {
     69                     if(x!="n"&&y=="n")//x为数字,y为n,复杂度+1 
     70                     {
     71                         ci[ceng]=ci[ceng-1]+1;
     72                         ans=max(ans,ci[ceng]);
     73                     }
     74                     else if(dayu(x,y))//x>y,此层循环不执行,做标记,时间复杂度不变 
     75                     {
     76                         not_do=true;
     77                         place=ceng;
     78                     }
     79                     else//否则时间复杂度不变 
     80                         ci[ceng]=ci[ceng-1];
     81                 }
     82             }
     83             else//退出循环 
     84             {
     85                 if(ceng==place)//不执行的循环已退出,重置标记 
     86                     not_do=false;
     87                 hash[alpha[ceng--]]=false;//销毁变量 
     88             }
     89         }
     90         if(wrong||ceng)//有语法错误 
     91             cout<<"ERR"<<endl;
     92         else if(ans&&pd(ans,fuzadu))//时间复杂度为O(n^ans) 
     93             cout<<"Yes"<<endl;
     94         else if(!ans&&fuzadu[2]=='1')//时间复杂度为O(1) 
     95             cout<<"Yes"<<endl;
     96         else
     97             cout<<"No"<<endl;
     98     }
     99     return 0;
    100 }

    代码写的比较乱神犇们不喜勿喷哈

    几个注意事项:

    1、每组数据一定要清空各种变量&数组!

    2、判断时间复杂度是否为O(n^w)要注意w不一定是一位数……我第一次就因为这个WA掉了好几个点

    3、写dayu()函数的时候要严谨一些……情况比较多,最好先用大量数据测试一下(血的教训啊)

  • 相关阅读:
    队列分类梳理
    停止线程
    Docker和Kubernetes
    Future、Callback、Promise
    Static、Final、static final
    线程池梳理
    TCP四次挥手
    http1.0、http1.x、http 2和https梳理
    重排序
    java内存模型梳理
  • 原文地址:https://www.cnblogs.com/LiHaozhe/p/9494537.html
Copyright © 2011-2022 走看看