例题 7-2 最大乘积(Maximum Product,UVa 11059)

前言

哇,关于这题,我真的有好多话说!!!首先,我这清奇的脑回路,在学暴力求解法这章,但是我的思路并不是暴力解题(好吧其实是因为一开始觉得暴力求解好麻烦,数据量大),花了两个小时把握的思路实现,但是WA了。

第一次调试的时候,终于发现了数据溢出了,数据真的好容易溢出,数据真的好容易溢出,数据真的好容易溢出!!!

最大值是1e+18,那这时候采用long long int就可以解决问题了,int 为 4 字节(数据表示范围:二进制32位,即-231——231-1,约为2 X 109),long long int 为8字节(数据表示范围:二进制64位,即-263——263-1,约为9 X 1018),但是,还是一直WA。。。啊它痛击我。。。。

然后,把它丢在一边,看剧去了。。。
下午4点的时候,找了一下uDebug上的一组数据,比对了一下,发现了隐藏及其深的Bug!一改,终于OK了。
我想着,如果自己多写几组测试数据,会不会惊喜地找出这个bug,但是这是小概率事件,但是但是,也不是不可能hhh。

题目

UVa原题传送门

思路

1、将输出的数据根据0,分隔成二维数组。
2、记录每行数据的负数的个数。
3、若个数为偶数,则对应行全部连乘上,得出该行的最大值。
4、若个数为奇数,则枚举各个起点,乘到 (个数-1)个负数,即当乘到最后一个负数时即结束,比较各个max得出该行的MAX。
5、比较每行的MAX,得出结果。

我的思路比较奇葩吧,看完暴力求解的思路,发现此处数据量不大,枚举子序列的起点和终点就行了。(其实我一开始也有差不多想到这个,为什么说差不多呢,因为我当时不知道如何确定乘到什么时候停下来,因为负数的负负得正…)现在总结当时为什么一票否决了这个,是因为我不知道连续子序列的要素就是 起点、终点呀,那就相当于枚举组合数了呀。
在这里插入图片描述
也就我的代码2000多了,没谁了哈哈哈哈哈哈哈哈哈哈哈哈

AC代码

在vjudge上一直出不了结果,就去了UVa原网站提交,还是那个味儿,网速还是那么感人(捂脸)
对了,还有,直接枚举起点和终点的代码往下翻,刷刷刷5分钟就写完了…(捂脸哭)

//@author reasonbao
//2020/3/21
//9:00-11:01  + WA后调试了半小时 + uDebug上找测试数据调试 
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;

const int kMaxn = 20;

int main() {
//	freopen("uva_11059_data_in.txt","r",stdin);	    //输入重定向,输入数据将从该文件读取
//	freopen("uva_11059_data_out.txt","w",stdout);	//输出重定向 
	int n;
	int kase = 0;
	while (cin >> n) {
		kase++;
//		if (kase > 1) cout << endl;	//打印空行
		 
		int s[kMaxn][kMaxn];
		int count_row = 0;
		//初始化二维数组
		for (int i = 0; i < kMaxn; i++) {
			for (int j = 0; j < kMaxn; j++) {
				s[i][j] = 0;
			}
		} 
		//由0分割,将一维数组转为二维数组
		int last_tmp = 0; 
		int is_empty = 1;
		for (int i = 0, j = 0 ,k = 0; i < n; i++) {
			int tmp;
			cin >> tmp;
			if (tmp == 0) {
				//二维数组非空、不是连续出现0 ,数组行下移 
				if (!is_empty && last_tmp) {
					j++;
					k = 0; 
				}
			}
			else {
				s[j][k++] = tmp;
				is_empty = 0;
			}
			count_row = j+1;
			last_tmp = tmp;
		} 
		
//		for (int i = 0; i < kMaxn; i++) {
//			for (int j = 0; j < kMaxn; j++) {
//				cout << s[i][j] << " ";
//			}
//			cout << endl;
//		} 
//		cout << "count_row = " << count_row << endl; 
		
		int count_negative[kMaxn];
		memset(count_negative, 0, sizeof(count_negative));
//		for (int i = 0; i < kMaxn; i++) cout << count_negative[i];
		for (int i = 0; i < count_row; i++) {
			for (int j = 0; s[i][j]; j++) {
				if (s[i][j] < 0) {
					count_negative[i]++;
				}
			}
		} 
//		for (int i = 0; i < kMaxn; i++) cout << count_negative[i];
		long long int max_arr[kMaxn];	//记录每一行的最大值 
//		int max_arr[kMaxn];	//记录每一行的最大值    Wrong Answer 越界咯,当18个元素均为10的情况下,答案为1e+18,int不够 
		for (int i = 0; i < count_row; i++) {
			max_arr[i] = s[i][0];	//每行的最大值,初始化为第一个元素的值
			 
			if (count_negative[i] % 2 == 0) {	//负数个数为偶数,全乘上 
				for (int j = 1; s[i][j]; j++) {
					max_arr[i] *= s[i][j];
				} 
			}
			else {	//负数个数为奇数(记为n)的情况,乘到n-1个奇数时停。 再取最大的那个
				for (int j = 0; s[i][j]; j++) {
					int count_neg = 0;
					long long int max_tmp = s[i][j]; 
//					if (s[i][0]  < 0)   count_neg++; 阿西,找到BUG了终于 
					if (s[i][j]  < 0)   count_neg++; 
					for (int k = j+1; s[i][k] && count_neg <count_negative[i]; k++) {
						if (s[i][k] < 0) count_neg++; 
						if (count_neg  == count_negative[i]) break;
						max_tmp = max_tmp * s[i][k];
					}
					if (max_tmp > max_arr[i]) max_arr[i] = max_tmp;
				}
			}
		}
		
//		for (int i = 0; i < count_row; i++) {
//			cout << "max = " << max_arr[i] << endl; 
//		}
		//数据全是0的情况——二维数组为空
		long long int ans = 0;
		if (is_empty) {
			ans = 0;
		} 
		else {
			sort(max_arr, max_arr+count_row);
			ans  =  max_arr[count_row-1];
			if (ans <= 0) ans = 0;			
		}
		
		printf("Case #%d: The maximum product is %lld.\n\n", kase, ans); 
	}
	return 0;
}
/*
10   0 0 1 2 -3 0 0 -1 2 0

*/

AC代码2.0(刷刷刷5分钟写完…)

#include <iostream>
#include <cstdio>

using namespace std;

long long int Operate(int *s, int begin, int end) {
	long long int max = s[begin];
	for (int i = begin+1; i <= end; i++) {	//注意,这里是<=end,end是数组下标 
		max *= s[i];
	}
	return max;
}

int main() {
	int n;
	int s[20];
	int kase = 0;
	while (cin >> n) {
		kase ++;
		for (int i = 0; i < n; i++) {
			cin >> s[i];
		}
		long long int ans = 0;
		//枚举起点和终点 
		for (int i = 0; i < n; i++) {
			for (int j = i; j < n; j++) {
//				cout << "begin = " << i << " end = " << j << endl; 
//				cout << "ans = "<<  Operate(s,i,j) << endl;
				if (Operate(s,i,j) > ans) ans = Operate(s,i,j);
			}
		}
		if (ans <= 0) ans = 0;
		printf("Case #%d: The maximum product is %lld.\n\n", kase,ans);
	}
	return 0;
} 

END
——————————————————————
Say say it again
说,再说一遍
Sometimes the memory was winding my mind
有时记忆缠绕在我的脑海中
——Say it again
——————————————————————

发布了41 篇原创文章 · 获赞 2 · 访问量 1642

猜你喜欢

转载自blog.csdn.net/qq_44296342/article/details/105012125