Link:http://codeforces.com/problemset/problem/7/E
Brief Introduction:一个表达式由多个“Macros”组成,每个Macro都为一个整体,如果最终的表达式使得运算顺序发生改变则称该表达式不安全
给你多个Macros和最终的表达式,询问该表达式是否安全
Algorithm:
要判断最终的表达式是否安全,就是要看其中的每个Macro是否安全,同时每一个运算符是否会使其整个变得不安全
我们发现要判断每个Macro的安全性也要经过同样的过程
从而将原问题化归为了解决多个相同的子问题并最终加合的问题。这样就可以想到利用递归或dp来解决问题
我们可以将每一部分划为4个状态,方便之后状态的加合
0:本身已经不安全
1:该macro在“/”或"-"后不安全
2:该macro仅在"/"后不安全
3:无论何时此皆安全
这样就构建了状态“安全程度”的单调性。判断两表达式加合起来的状态时,仅要判断其是否大于某个安全程度即可
Code:
#include <bits/stdc++.h> using namespace std; int n,len=0,w=0; string t; char s[200]; map<string,int> mp; int eval(int l,int r) { for(int i=r,w=0;i>l;i--) if(w+=(s[i]==')'),w-=(s[i]=='('),!w&&(s[i]=='-' || s[i]=='+')) { int L=eval(l,i-1),R=eval(i+1,r); return L&&R&&(s[i]!='-' || R>1); //对"-"后的判断为安全程度是否大于1 } for(int i=r,w=0;i>l;i--) if(w+=(s[i]==')'),w-=(s[i]=='('),!w&&(s[i]=='*' || s[i]=='/')) { int L=eval(l,i-1),R=eval(i+1,r); return (L>1)&&(R>1)&&(s[i]!='/' || R>2)?2:0; } if(s[l]=='(') //有了括号,就没有1、2状态了 return eval(l+1,r-1)?3:0; string a(s+l,s+r+1); return mp.count(a)?mp[a]:3; } int Get() { gets(s); for(int i=len=0;s[i];i++) if(s[i]!=' ') s[len++]=s[i]; return eval(0,len-1); } int main() { cin >> n; for(int i=1;i<=n;i++) { scanf(" #%*s");cin >> t; mp[t]=Get(); } cout << (Get()?"OK":"Suspicious"); return 0; }
Review:
1、字符串读入技巧:
scanf中*s,*d均为省略符号,只读取而不存储
使用gets函数可读取这一行剩下的所有内容
2、对此类包含括号匹配问题的通用技巧:
在循环时用一个变量记录此时括号是否已经匹配,是则进行递归
3、当发现可以将问题变为更小规模分别处理时,使用递归手法,正确将状态分类
4、如果状态种类较多,可以构建状态从“好”到“坏”的单调性从而方便判断