Sicily 1050. Numbers & Letters

Description
In the early 80’s, a popular TV show on Dutch television was ‘Cijfers en Letters’ (Numbers and Letters). This game consisted of two game elements, in which the main goal was to outclass your opponent. Letters is a game in which you are given a number of letters with which you should form the longest Dutch word possible. Since Dutch is a very hard language to learn we will postpone implementation of this game element until after the contest. 
For the second game element ‘Numbers’ 5 different numbers are chosen, together with a target number. The aim is to use some arithmetic on ( some of) the five numbers to form the target number. Each number can be used only once. It might not be possible to form the target number given the input numbers, in that case the largest number smaller than the target number that can be calculated should be given. The only mathematical operations allowed are: +, -, *, /.  All intermediate results should be integers, so division is not always allowed (e.g. (2*2)/4 is OK, but 2*(2/4) is not). 
Examples: 
- If the 5 numbers are 1, 2, 3, 7 and 100 and the target number is 573, the target number can be reached as follows: (((100-1)*2)-7)*3. -If the 5 numbers are 3, 26, 78, 12 and 17, and the target number is 30, the target number can be reached as follows: (78*3)-(12*17). 
- If the 5 numbers are 67, 69, 58, 22, 2, and the target number is 929, the target number cannot be reached, but the largest number smaller than the target number that can be reached is 923 = (22-(67-58))*(69+2). 
Your assignment is to write a program that calculates the best approximation from below of the target number using arithmetic on the 5 given numbers. Note that if it is not possible to reach the exact number, you should give the largest reachable number below the target number.
Input
The first line contains the number of runs, N. The next N lines consist of six numbers separated by a space. The first 5 numbers Mi, 1≤Mi≤100, are the numbers you can use to calculate the target number. The sixth number is the target number T, 0≤T≤1000.
Output
The output consists of N rows, each containing the best approximation of the target number using the 5 given numbers.
Sample Input
 Copy sample input to clipboard
3
1 2 3 7 100 573
3 26 78 12 17 30
67 69 58 22 2 929
Sample Output
573
30 
923
 

个人分析:

这题用DFS想应该不难,用一个数组作为当前可以继续运算的数值,然后选出两个进行四种运算。其中要考虑的就是减法和除法运算。


如果你一直wrong answer在test case2,很有可能就是没有看清题目,题目中要求可以只选择部分数字进行数学运算。

如果你一直wrong answer在test case3,很有可能就是在做减号运算的时候,直接把得数为负数的情况给舍去了。比如说样例

1
0 0 -1 0 5 -2
正常输出应该是-4,可以-1-5=-4,而如果没有考虑减法可以为负数的时候,可能就变成-1*5=-5了。显然-4要比-5大。

代码如下:

#include <stdio.h>
#include <memory.h>
#include <cmath>
#include <climits>

// 用于数学运算的个数
#define GIVEN_NUM 5

using namespace std;

void dfs (long& ans, long target, long* arr, int num);

int main() {
    int n;
    scanf("%d", &n);
    long* num = new long[GIVEN_NUM];
    long ans;
    long target;
    while (n--) {
        ans = LONG_MIN;
        for (int i = 0; i < GIVEN_NUM; i ++)   // 输入用于运算的数字
            scanf("%ld", num+i);
        scanf("%ld", &target);                            // 输入目标数值
        dfs(ans, target, num, GIVEN_NUM);  // 进行模拟
        printf("%ld\n", ans);
    }
    return 0;
}

// ans为当前运算的最小数值,target为目标数值,arr为表达式各部分的数值(包括未运算的数字),num为数字的长度
void dfs (long& ans, long target, long* arr, int num) {
    long value = arr[num-1];    // 取出最后一位,这里因为每次运算后的结果放在数组最后。
    ans = (value <= target && value > ans) ? value : ans;  // 判断是不大于目标数,且比先前运算的结果更大

    if (ans == target || num == 1)  // 剪枝,避免重复运算
        return;

    long* tmpArr = new long[num-1]; // 用于存放运算后的数值
    for (int i = 0; i < num; i ++) {             // 取出i
        for (int j = i+1; j < num; j ++) {     // 取出异于i的j
            int count = 0;
            for (int k = 0; k < num; k ++)
                if (k != i && k != j)
                    tmpArr[count++] = arr[k]; // 保存i和j之后的其他数字,用于下一轮计算

            tmpArr[count] = arr[i]+arr[j];    // 加法运算
            dfs (ans, target, tmpArr, num-1);
            
            
            tmpArr[count] = arr[i]-arr[j];   // 减法运算
            dfs (ans, target, tmpArr, num-1);
            tmpArr[count] = arr[j]-arr[i];
            dfs (ans, target, tmpArr, num-1);

            tmpArr[count] = arr[i]*arr[j];  // 乘法运算
            dfs (ans, target, tmpArr, num-1);

            if (arr[j] != 0 && arr[i] % arr[j] == 0) { // 除法运算
                tmpArr[count] = arr[i] / arr[j];
                dfs (ans, target, tmpArr, num-1);
            }

            if (arr[i] != 0 && arr[j] % arr[i] == 0) {
                tmpArr[count] = arr[j] / arr[i];
                dfs (ans, target, tmpArr, num-1);
            }
        }
    }
    delete tmpArr;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值