zoukankan      html  css  js  c++  java
  • 选择我自己的算法 2012年CCC加拿大高中生信息学奥赛

    在水城,你可能会看到一些鹅。你怎么在计算器上看到鹅呢?方法是输入35336,然后把计算器倒过来看,你就能看到gEESE——鹅了。

    现在你的计算器的减号不给力了,只有+号和×号可以用,而且也只有部分数字可以工作。现在的任务是对于这个破烂的计算器能否通过简单的数字和固定数目的运算次数得到一个给定的目标值。

    注意这个计算器的运算在被按下的时候就立即执行了,而不需要按照运算符优先级的规则。(见样例2)

    输入描述

    第一行输入一个整数W,表示你能够且必须使用的运算个数。W是是一个介于0到6之间的整数。结下来的一行是一个整数D(1 ≤ D ≤ 10),可以工作的数字键的个数。接下来的D行给出了这D个可以工作的数字键,这些数字键是0-9之间的互不重复的整数。然后给出一个整数V(1 ≤ V ≤ 5),即目标值的个数,接下来的V行每行一个介于0到5,000,000(包含)的整数,代表你需要用过计算器算出来的数值。

    输出描述

    输出包含V行,对应着V个目标值。每行是Y或者N,代表对应的目标值能在使用这D个数字并且刚好在W次运算的情况下被计算得到或者不能被计算得到。精确的说,一个目标值T能够计算得到的话,那是通过从D个数字钟的某个数字开始,通过加或乘其这些数字刚好W次,然后最后得到数值T。数字是可以重复使用的。数字也不需要全部被用完。但注意你不可以输入多位数。

    样例输入 Sample Input

    样例输入1

    6

    3

    6

    7

    8

    1

    35336

    样例输入2

    3

    2

    4

    9

    2

    97

    88

    样例输出 Sample Output

    样例输出1:

    Y

    样例输出2:

    N

    Y

    数据范围及提示 Data Size & Hint

    对于第二个数据,虽然4×4+9×9 = 97,但是由于计算的顺序是从左往右依次进行的,所以输出N。第二行,9+9+4*4就得到了88.

    这道题目第一印象其实可以直接搜索
    最多6个运算符7个数字,总状态共有2的6次方乘10的7次方
    这个数远远大于计算机能共接受的1亿……

    我们可以注意到任何一个答案,它一定由前一个数乘或加而得来
    那么我们可以倒过来搜,如果目前得数可以被除或被加而得来,那么我们就进行除和减的递归,直到已经递归了W次(或者W加减1?次),看所得数是否可行。

    这样我们的状态数大大被消减,饱和状态数大概是50000000*6左右,但是我们由于剪枝的存在根本不可能运行这么多次,估计算法完全可以保证状态数大大低于1000000(应该是……)

     

    #include <iostream>

    using namespace std;

    int ANS,W;

    int N;

    int V;

    bool q[100000000];

    int temp;

    bool can(int ans,int k)

    {

    if (k==0)

     {

      if (ans<=9)

      {

       if (q[ans])

         return true;

       else

         return false;

       }

       else

         return false;

     }

    for (int i=0;i<=9;i++)

     if (q[i])

     if (can(ans-i,k-1))

       return true;

    for (int i=1;i<=9;i++)

     if (ans%i==0)

       if (q[i])

       if (can(ans/i,k-1))

      return true;

    if (ans==0)

     if (can(0,k-1))

       return true;

    return false;

    }

    int main()

    {

    cin>>W;

    cin>>N;

    for (int i=1;i<=N;i++)

    {

    cin>>temp;

    q[temp] = true;

    }

    cin>>V;

    for (int i=1;i<=V;i++)

    {

    cin>>ANS;

    if (can(ANS,W)) 

    cout<<"Y"<<endl;

    else

    cout<<"N"<<endl;

        }

    return 0;

    }

  • 相关阅读:
    Android 去除最上面应用名称及图标
    Android 仿QQ消息界面
    多线程断点续传及下载
    android 断点下载---XUtils
    Android判断网路是否畅通加权限
    Android_按两次返回键退出程序和长按返回键退出程序
    Android JPush(极光推送)的使用教程
    使用VS2013自带的PreEmptive Dotfuscator and Analytis来混淆C#代码
    Entity Framework 6连接Oracle、Postgresql、SQLite、LocalDB数据库字符串详解
    Fluent Nhibernate 数据库配置
  • 原文地址:https://www.cnblogs.com/D-AngeloRussell/p/7240196.html
Copyright © 2011-2022 走看看