Codevs 1268 选择我自己的算法

来源:互联网 发布:室内定位 指纹算法 编辑:程序博客网 时间:2024/05/22 04:54

题目描述 Description
In Waterloo, you probably have seen some geese. How can you see geese with your calculator? Start with 6, add 7, multiply by 6, multiply by 8, add 7, multiply by 8, and multiply by 7, giving 35336. Then if you flip your calculator upside down, it says gEESE:

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

You want to write a program to help automatically build tricks of this type. However, your calcula- tor has a lot of broken buttons: the only mathematical operators that work are + and ×, and only a few of the digits work. Your goal is to figure out whether your half-broken calculator can achieve a given target value, using single-digit inputs and a fixed number of operations.

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

Note: the calculator performs the operations as soon as they are entered, rather than following any rules for order of operations (see Sample Input 2).

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

输入描述 Input Description
The first line of input is W, the exact number of operations you must use. W will be an integer between 0 and 6. The second line of input is 1 ≤ D ≤ 10, the number of working digit keys. On each of the D following lines, a working digit is given; these values are distinct integers from 0 to 9. Finally, an integer 1 ≤ V ≤ 5 is given, the number of target values; on each of the following V lines there is an integer between 0 and 5000000 (inclusive) giving a target value which you’d like to achieve on your calculator.

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

输出描述 Output Description
The output consists of V lines corresponding to the target values; each line contains “Y” if that target value can be achieved, and “N” if it cannot be achieved, using exactly W operations with the D given digits.
Precisely, a target value T can be achieved if, starting with one of the D digits, and then by adding or multiplying exactly W times by one of the digits, you end up with T. Digits can be re-used, and you do not need to use all of the digits. You cannot enter multi-digit numbers.

输出包含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
First line: we cannot achieve 97 using the rules of this calculator, so the output is N (even despite that 4×4+9×9 = 97, when the typical order of operations rules are taken into account). Second line: start with 9, add 9, add 4, and multiply by 4; this gives 88.

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

//倒搜:从结果入手,做相反运算 #include<iostream>#include<cstdio>using namespace std;int num[12],t,n,m; bool ok;void dfs(int h,int sum){    if(h==t)    {//达到运算上线         for(int i=1;i<=n&&!ok;i++)        if(sum==num[i])//缩小的结果在给定数中         ok=1;        return;    }    for(int i=1;i<=n;i++)    {//daosou(*,+→/,-) && 找整处后的值,减小搜索范围,整除得不到整数,进行减法         if(num[i]!=0&&sum%num[i]==0) dfs(h+1,sum/num[i]);        dfs(h+1,sum-num[i]);        //通过-和/操作得到的当前的sum,一定能再通过* && +回到原数,所以sum缩到一定小的时候,        //只要是等于给定的num中的数,那一定能逆着算回到原数,所以此方法一定成立    }}int main(){    cin>>t>>n;    for(int i=1;i<=n;i++)    scanf("%d",&num[i]);    cin>>m;    int a;    for(int i=1;i<=m;i++)    {        ok=0;        scanf("%d",&a);        dfs(0,a);        if(!ok) cout<<"N\n";        else cout<<"Y\n";    }    return 0;}
原创粉丝点击