《挑战程序设计》编程题抽签

image

由于题目中限定了k的大小,所以实际上如果用int也不存在溢出的问题。因为int类型最大也有21亿多。

下面是目前想到的解法。

#include<iostream> 
#include<fstream>
#include<string>    //在vs2013里写成cstring是错误的。所放的位置有无特殊要求?
#include<algorithm>
#include<time.h>
using namespace std;


int main(){

    //重定向输入流到data.in文件。特别注意:在vs2013里直接调试时,"."号表示的含义当前解决方案中正在运行的工程的根目录,
    //而不是该工程的debug或release目录下。但是如果是在工程目录下直接点击生成的exe文件,则是以exe文件所在目录进行查找。
    ifstream fin;
    fin.open("./data.in");
    cin.rdbuf(fin.rdbuf());   // assign file's streambuf to cin

    //下面是data.in里的内容(不包含注释行):
        /*********
        8
        106
        36 28 75 17 3 62 7 21
        *************/

    unsigned int numCnt = 0;
    cin >> numCnt;
    unsigned int givenSum = 0;  
    cin >> givenSum;
    unsigned int *numArr = new unsigned int[numCnt+1];
    for (int i = 0; i < numCnt; i++){
        cin >> numArr[i];
    }

    //开始进行程序计时
    long beginTime = clock();//获得开始时间,单位为毫秒

    //对输入的数据进行排序
    //sort(numArr, &numArr[numCnt+1]);  error:第二个参数应该 是&numArr[numCnt],new运算符中表示的是元素个数,这里是下标。
    sort(numArr, &numArr[numCnt]);
    unsigned int *numArrWithNoSameElement = new unsigned int[numCnt];   //如果有重复元素,由这里的空间会分配地有点多。
    unsigned int curValue = numArr[0];
   
    //去除重复元素得到一个新的数组。
    int newArrIndex = 1;
    numArrWithNoSameElement[0] = numArr[0];
    for (int i = 1; i < numCnt; i++){
        if (numArr[i] == curValue)  continue;
        else{
            numArrWithNoSameElement[newArrIndex++] = numArr[i];  //注意结束时,newArrIndex++,多执行了一次。但是如果将其理解成元素个数,则是正确的。但为了与其名称相符,将其加1
        }
    }

    newArrIndex--;
   
    //erro:因为上面newArrIndex++多执行了一次,这里第二个参数不能再加1。
    //另外,作为c内存管理函数,面向的是字节,realloc第二个表示的是字节数,而不是元素个数。
    //int *numArrWithExactSpace= (int*)realloc(numArrWithNoSameElement, newArrIndex + 1);
   
    unsigned int * numArrWithExactSpace = (unsigned int*)realloc(numArrWithNoSameElement, (newArrIndex + 1)*sizeof(unsigned int));
    unsigned int minAtCurScene = 0;
    unsigned int maxAtCurScene = 0;

    //整体判断是否可能有正确结果。
    minAtCurScene = numArrWithExactSpace[0] << 2; 
    maxAtCurScene = numArrWithExactSpace[newArrIndex] << 2;
    int res=-1;
   
    if (minAtCurScene>givenSum || maxAtCurScene < givenSum) {
        cout << "不可能匹配" << endl; 
        //return -1;
        res = -1;
        goto Returnblock;
    }
    else{
        if (minAtCurScene == givenSum || maxAtCurScene == givenSum){
        cout << "有唯一匹配" << endl;
        //return 1;
        res = 1;
        goto Returnblock;
        }       
       
    }

    bool  isMatch = false;
    //因为给定的和在整个数组的最小值和最大值之间,所以要进行进一步判断。
    for (int i = 0; i < newArrIndex+1; i++){      //这里的newArrIndex要加1   
       
        minAtCurScene = numArrWithExactSpace[i] << 2;
        maxAtCurScene = numArrWithExactSpace[i] + numArrWithExactSpace[newArrIndex]*3;
       
        if (minAtCurScene > givenSum)  {
            //cout << "1不存在匹配情况。" << endl;
            //return -1;
            break;  //条件成立,可能是因为之前的情况下,和的值不能匹配,导致内层循环继续迭代。
        }
        else if (maxAtCurScene<givenSum) continue;  //这可能作为一个理解break和continue在程序中应用的典型案例。

        for (int j = i; j<newArrIndex+1; j++){
            minAtCurScene = numArrWithExactSpace[i]+numArrWithExactSpace[j]*3;
            maxAtCurScene = numArrWithExactSpace[i] + numArrWithExactSpace[j]+ (numArrWithExactSpace[newArrIndex] <<1);
            if (minAtCurScene > givenSum)  {
                //cout << "2不存在匹配情况。" << endl;  return -1;
                break;
            }
            else if (maxAtCurScene<givenSum) continue;

            for (int k = j; k < newArrIndex+1; k++){
                //注意移位运算符用在语句中时,必须要尽可能加括号,增加可读性,并且防止意外发生。比如下面的例子。本意是左移一位,只对第三项进行,但是实际上是对前面的三项各进行。
                //minAtCurScene = numArrWithExactSpace[i] + numArrWithExactSpace[j]+numArrWithExactSpace[k]<<1;  error:逻辑错误,移位运算符错误。
                minAtCurScene = numArrWithExactSpace[i] + numArrWithExactSpace[j] + (numArrWithExactSpace[k] << 1);
                maxAtCurScene = numArrWithExactSpace[i] + numArrWithExactSpace[j] + numArrWithExactSpace[k]+ numArrWithExactSpace[newArrIndex] ;
                if (minAtCurScene > givenSum) {
                    //cout << "3不存在匹配情况。" << endl; return -1;
                    break;
                }
                else if (maxAtCurScene<givenSum) continue;

                for (int m = k; m < newArrIndex+1; m++){
                    if (numArrWithExactSpace[i]+numArrWithExactSpace[j] + numArrWithExactSpace[k] + numArrWithExactSpace[m] == givenSum){
                        cout << "成功匹配:" << numArrWithExactSpace[i]<<" + "<< numArrWithExactSpace[j] <<" + " << numArrWithExactSpace[k]<<" + " <<numArrWithExactSpace[m] <<"="<<givenSum<<endl;
                       
                        //return 1;   不规范的做法,如果有可能尽可能在一个函数中只包含一个return 语句。甚至在函数中使用goto语句也在所不惜。
                        goto Returnblock;
                    }
                }
            }
        }       
    }

    if (!isMatch) {
        cout << "匹配失败" << endl;
        //return 0;
        res = 0;
        goto Returnblock;
       
    }

Returnblock:
        long endTime = clock();//获得结束时间
        cout << "beginTime:" << beginTime << endl
            << "endTime:" << endTime << endl
            << "endTime-beginTime:" << (double)(endTime - beginTime) / CLOCKS_PER_SEC<<" s"<< endl;
        system("pause");
        return res;

}

image

转载于:https://my.oschina.net/ray1421/blog/694078

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值