浅谈随机化算法--模拟退火题目

一、概述
     随机化算法是一种很好的算法,当我们在无法想出正解或者正解很难写的时候。
二、例题
     
BSOJ1054 LuoguP1054 CODEVS1107 -- 【NOIP 2005提高】等价表达式
Description
  明明进了中学之后,学到了代数表达式。有一天,他碰到一个很麻烦的选择题。这个题目的题干中首先给出了一个代数表达式,然后列出了若干选项,每个选项也是一个代数表达式,题目的要求是判断选项中哪些代数表达式是和题干中的表达式等价的。
  这个题目手算很麻烦,因为明明对计算机编程很感兴趣,所以他想是不是可以用计算机来解决这个问题。假设你是明明,能完成这个任务吗?

  这个选择题中的每个表达式都满足下面的性质:
  1.表达式只可能包含一个变量‘a’。
  2.表达式中出现的数都是正整数,而且都小于10000。
  3.表达式中可以包括四种运算‘+’(加),‘-’(减),‘*’(乘),‘^’(乘幂),以及小括号‘(’,‘)’。小括号的优先级最高,其次是‘^’,然后是‘*’,最后是‘+’和‘-’。‘+’和‘-’的优先级是相同的。相同优先级的运算从左到右进行。  (注意:运算符‘+’,‘-’,‘*’,‘^’以及小括号‘(’,‘)’都是英文字符)
  4.幂指数只可能是1到10之间的正整数(包括1和10)。
  5.表达式内部,头部或者尾部都可能有一些多余的空格。
  下面是一些合理的表达式的例子:
    ((a^1) ^ 2)^3,a*a+a-a,((a+a)),9999+(a-a)*a,1 + (a -1)^3,1^10^9……
Input
  输入的第一行给出的是题干中的表达式。第二行是一个整数n(2 <= n <= 26),表示选项的个数。后面n行,每行包括一个选项中的表达式。这n个选项的标号分别是A,B,C,D……
  输入中的表达式的长度都不超过50个字符,而且保证选项中总有表达式和题干中的表达式是等价的。
Output
  输出包括一行,这一行包括一系列选项的标号,表示哪些选项是和题干中的表达式等价的。选项的标号按照字母顺序排列,而且之间没有空格。
Sample Input
( a + 1) ^2
3
(a-1)^2+4*a
a + 1+a
a^2 + 2 * a * 1 + 1^2 + 10 -10 +a -a
Sample Output
AC
Hint
  对于30%的数据,表达式中只可能出现两种运算符‘+’和‘-’;
  对于其它的数据,四种运算符‘+’,‘-’,‘*’,‘^’在表达式中都可能出现。
  对于全部的数据,表达式中都可能出现小括号‘(’和‘)’。

显然,这道题使用字符串强行处理是不明智的,那么,我们该怎么做呢?
我们可以随机几个数字(实战告诉我们-1,0,1似乎就可以了)代进去看是否相等。
#include<iostream>
#include<iomanip>
#include<cstring>
#include<cmath>
#include<cstdio>
#define mod 10003
using namespace std;
int j,f[15],n,k;
string s,x;
int find_number(string s,int l,int r,int &t)
{
        t=0;
        for(int i=l;i<=r;i++)
        {
                if(s[i]<'0'||s[i]>'9')return 0;
                else t=t*10+s[i]-'0';
        }
        return 1;
}
int find_low(string s,int l,int r)
{
        int k=0,t=0,j=0;
        for(int i=r;i>=l;i--)
        {
                if(s[i]=='a'||(s[i]<='9'&&s[i]>='0'))continue;
                if(s[i]==')'){t++;continue;}
                if(s[i]=='('){t--;continue;}
                if((s[i]=='+'||s[i]=='-')&&t==0)return i;
                if(!k&&!t&&s[i]=='*'){k=i;continue;}
                if(!j&&!t&&s[i]=='^'){j=i;continue;}
        }
        if(!k)return j;
        return k;
}
int cal(int a,char ch,int b){
    int t=1;
    if(ch=='+') return ((a+b)%mod+mod)%mod;
    if(ch=='-') return ((a-b)%mod+mod)%mod;
    if(ch=='*') return ((a*b)%mod+mod)%mod;
    if(ch=='^') for(int i=1;i<=b;i++)
                   t=((a*t)%mod+mod)%mod;
    return t;
}
int matchr(string s,int l,int r)
{
        int tot=1;
        for(int i=l+1;i<=r;i++)
        {
                if(s[i]=='(')tot++;
                else if(s[i]==')')tot--;
                if(tot==0)return i;
        }
}
void delspace(string &s)
{
        string tmp=" ";
        int len=s.length();
        for(int i=0;i<len;i++)
          if(s[i]!=' ')tmp+=s[i];
        s=tmp;
}
int t(string s,int l,int r)
{
        int pos,left,right,k;
        if(s[l]=='('&&matchr(s,l,r)==r)return t(s,l+1,r-1);
        if(find_number(s,l,r,k))return k;
    if(s[l]=='a'&&l==r)return j;
    pos=find_low(s,l,r);
    left=t(s,l,pos-1);
    right=t(s,pos+1,r);
    k=cal(left,s[pos],right);
    return k;
}
int main(){
        getline(cin,s);
        delspace(s);
        cin>>n;
        for(j=0;j<=4;j++)f[j]=t(s,1,s.length()-1);
        getline(cin,x);
        for(int i=1;i<=n;i++)
        {
                getline(cin,x);
        delspace(x);
        for(j=0;j<=4;j++)
                {
                k=t(x,1,x.length()-1);
                if(k!=f[j])break;
        }
        if(j>4)cout<<char(i+'A'-1);
        }
    return 0;
}




bzoj2396 POJ3318 神奇的矩阵
Description
    给出三个行数和列数均为N的矩阵A、B、C,判断A*B=C是否成立。
Input
    题目可能包含若干组数据。
    对于每组数据,第一行一个数N,接下来给出三个N*N的矩阵,依次为A、B、C三个矩阵。
Output
    对于每组数据,若A*B=C成立,则输出Yes,否则No。每个答案占一行。
Sample Input
1
2
2
100
Sample Output
  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值