洛谷 P3952 时间复杂度 【模拟】【2017 noip d1t2】
这个的模拟比较复杂。大方向是记录count表示有效的循环层数(x>=y时count不++),还有维护一个enter数组,enter[i]代表第i个循环体能不能进去,再维护contri数组,contri[i]表示第i个循环体对count有没有贡献。
然后模拟一下语法错误的情况,注意有错误输入还得输进去,还有得到w(注意w,x,y是十位数的可能)
并没有复杂的算法,这就是模拟的魅力吧。
一共11个样例点,每个点9分,我是下载数据点一个一个调过的你敢信。。。
从此以后再也不怕模拟,因为我已经为模拟付出了最高的代价
1 #include<iostream> 2 #include<stack> 3 #include<map> 4 #include<cstring> 5 using namespace std; 6 7 stack<char> st; 8 map<char,bool> m; 9 10 int enter[1005],contri[1005]; 11 int main(){ 12 13 int t; cin>>t; 14 while(t--){ 15 int count=0,id=0,ans=0;//当前的有效循环层数 16 int length; string O; cin>>length>>O; 17 bool err=false; 18 19 for(int i=1;i<=length;i++){ 20 char type; cin>>type; 21 if(type=='F'){ 22 char c; cin>>c; string start,end; cin>>start>>end; 23 24 if(m[c]) err=true; 25 if(err) continue; 26 27 m[c]=true; st.push(c); 28 if(id!=0 && enter[id]==0) enter[++id]=0;//如果上一个循环没进去,这一个一定也没进去 29 else if(start=="n") { 30 if(end=="n") enter[++id]=1; 31 else enter[++id]=0; 32 } 33 else if(end!="n") {//常数到常数,看x和y哪个大能进去,但对count没有贡献 34 int x,y; 35 if(start.length()==2) x=(int(start[0])-48)*10+(int(start[1])-48); 36 else x=int(start[0]-48); 37 38 if(end.length()==2) y=(int(end[0])-48)*10+(int(end[1])-48); 39 else y=int(end[0]-48); 40 41 if(x>=y) enter[++id]=0;//进不去 42 else enter[++id]=1; 43 } 44 else { enter[++id]=1; count++; contri[id]=1; } 45 } 46 else{//是E 47 if(st.empty()) err=true; 48 if(err) continue; 49 50 ans=max(count,ans); 51 if(contri[id]) { count--; contri[id]=0; } 52 m[st.top()]=false; st.pop(); 53 id--; 54 } 55 } 56 57 int ge=-1,w; 58 if( O[2]!='1' && O[5]!=')' ) ge=int(O[5])-48; //w是个十位数 59 if( O[2]!='1' && ge!=-1) w=(int(O[4])-48)*10+ge; 60 else if(O[2]!='1') w=int(O[4])-48; 61 62 if(!st.empty()) err=true; 63 if(err) cout<<"ERR"<<endl; 64 else if( (ans==0 && O[2]=='1') || ans==w ) cout<<"Yes"<<endl; 65 else cout<<"No"<<endl; 66 67 while(!st.empty()) st.pop(); 68 m.clear(); 69 memset(contri,0,sizeof(contri)); 70 } 71 72 73 return 0; 74 }