由于题目中限定了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;
}