Uva 11059 最大乘积

水题

教训:

对于复杂的参数不要使用宏定义函数,尤其是函数嵌套使用时,函数涉及++、- -之类的。

前缀和思想求解

#include<iostream>
using namespace std;
typedef long long ll;
int main()
{
	int n,l=0;
	while (cin >> n)
	{
		l++;
		int arr[18];
		ll f[18][18] = {};
		for (int i = 0; i < n; i++)
			cin >> arr[i];
		f[0][0] = arr[0];
		int max = 0;
		for (int i = 1; i < n; i++)
		{
			f[0][i] = f[0][i - 1] * arr[i];
			if (f[0][i] > max)max = f[0][i];
		}
		for (int i = 1; i < n; i++)
		{
			for (int j = 0; j < n; j++)
			{
				if (i > j)continue;
				f[i][j] = f[0][j] / f[0][i - 1];
				if (f[i][j] > max)max = f[i][j];
			}
		}
		cout <<"Case #"<<l<<": The maximum product is "<< max <<"."<< endl;
	}
	return 0;
}

时间复杂度是O(n^2)

DP动态规划

 如果直接写固定终点类的状态(如dp(i)表示以i结尾的连续序列的最大乘积),则不能求解,因为问题不满足最优化原理。即过程最优解可得到这一策略的最优解,比如2 5 -1 -2,2*5=10,就会不会乘以-1才是阶段三的最好决策,而在阶段四时10更不会选择乘以-2变成负数,所以明显解为10而非20。

 那么如何使用动态规划求解呢?很简单,解决问题就好了!问题在于某一个状态为负值,但它可能涉及以后的其他状态的决策(比如25-1就应该涉及第四阶段是否*2的决策),所以我们尝试使用另一个dp数组记录最小值,当在一个状态做决策时也要比较最小值的情况。

考虑状态有两种:
 第一种dpMax(i)表示步步选择最好决策(从第二步开始)时i阶段所形成的情况。
 第二种dpMin(i)表示步步选择最差决策(从第二步开始)时i阶段所形成的情况。

考虑状态:
 dpMax(0)=arr[0];
 dpMin(0)=arr[0];
 dpMax[i]=Max(dpMax[i-1]*a[i],a[i],dpMin[i-1]*a[i]);
 dpMin[i]=Min(dpMin[i-1]*a[i],a[i],dpMax[i-1]*a[i]);

题解代码(含注释)

#include<iostream>
int Max(int a, int b)//在复杂时使用宏定义函数会出错,比如++或者嵌套调用宏定义
{
	return a > b ? a : b;
}
int Min(int a, int b)//切记在复杂参数时不要使用宏定义!!
{
	return a < b ? a : b;
}
using namespace std;
int dp[18];//存储最好情况
int dpMin[18];//存储最坏情况
int main()
{
	int n,i=0;
	while (cin >> n)//输入序列元素个数
	{
		i++;//记录第几个样例
		int arr[18];
		for (int i = 0; i < n; i++)//输入序列
			cin >> arr[i];
		int max = arr[0]; //要将max初始化为arr[0]也即dp[0](不初始化为方便的0也因为是这个原因)
		dp[0] = arr[0];	  //初始化状态
		dpMin[0] = arr[0];//初始化状态
		for (int i = 1; i < n; i++)//从1开始状态转移!(转移过程中的状态会和max比较,但没有状态0,所以一定要将Max初始化为状态0)
		{
			dpMin[i] = Min(Min(arr[i], arr[i] * dpMin[i - 1]), arr[i] * dp[i - 1]);//状态转移
			//if (i == n-1)cout << arr[i] << " " << arr[i] * dpMin[i - 1] << " " << arr[i] * dp[i - 1] << endl;
			dp[i] = Max(Max(arr[i], arr[i] * dpMin[i - 1]), arr[i] * dp[i - 1]);  //状态转移
			if (dp[i] > max)max = dp[i];//比较更新max(所有dp的情况的最大那一种就是最优解)
		}
		cout << "Case #"<<i<<": The maximum product is " << (max>0?max:0)<< "." << endl;//输入(max如果小于0要输出0)
	}
	return 0;
}
上一篇:The Monocycle UVA - 10047 bfs


下一篇:Kickdown UVA - 1588