UVa 787 - Maximum Sub-sequence Product

題目:計算一個序列的最大子段乘機。

分析:動態規劃(DP)。dp過程和最大子段和類似。

            因為乘數有負數,所以需要保留最小值(最小的負數乘以負數就是最大值);

            狀態定義:max(i)為以i結束的子段的最大乘機,min(i)為以i結束的子段的最小乘機;

            轉移方程:這裡 需要列出一個表格;

           

            其中item(i)為當前元素數值,之所以是6種而不是8種,是因為那兩種不可能成立(min > max);

            表格中沒有給出等於零的情況(此時min和max為0);

說明:注意負數的進位,╮(╯▽╰)╭。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int data[101];
int max[101][555];
int min[101][555];
int zero[555];
int one[555];

void output(int ans[])
{
	int end = 550;
	while (end > 0 && !ans[end]) {
		end --;
	}
	while (end >= 0) {
		printf("%d",ans[end --]);
	}
	puts("");
}

void mul(int ans[], int a[], int b)
{
	for (int i = 0; i < 550; ++ i) {
		ans[i] = a[i]*b;
	}
	for (int i = 0; i < 550; ++ i) {
		if (ans[i] > 9 || ans[i] < -9) {
			ans[i+1] += ans[i]/10;
			ans[i]   %= 10;
		}
	}
}

int bigger(int a[], int b[])
{
	for (int i = 550; i >= 0; -- i) {
		if (a[i] != b[i]) {
			return a[i] > b[i];
		}
	}
	return 0;
}

int main()
{
	memset(zero, 0, sizeof(zero));
	memset(one, 0, sizeof(one));
	one[0] = 1;
	
	int count = 1;
	while (~scanf("%d",&data[count])) {
		while (data[count] != -999999) {
			count ++;
			scanf("%d",&data[count]);
		}
		
		memset(min, 0, sizeof(min));
		memset(max, 0, sizeof(max));
		for (int i = 1; i < count; ++ i) {
			if (data[i] > 0) {
				if (bigger(min[i-1], zero)) {
					mul(max[i], max[i-1], data[i]);
					mul(min[i], one, data[i]);
				}else if (bigger(zero, max[i-1])){
					mul(max[i], one, data[i]);
					mul(min[i], min[i-1], data[i]);
				}else if (bigger(max[i-1], zero) || bigger(zero, min[i-1])) {
					mul(max[i], max[i-1], data[i]);
					mul(min[i], min[i-1], data[i]);
				}else {
					mul(max[i], one, data[i]);
					mul(min[i], one, data[i]);
				}
			}else if (data[i] < 0) {
				if (bigger(min[i-1], zero)) {
					mul(max[i], one, data[i]);
					mul(min[i], max[i-1], data[i]);
				}else if (bigger(zero, max[i-1])){
					mul(max[i], min[i-1], data[i]);
					mul(min[i], one, data[i]);
				}else if (bigger(max[i-1], zero) || bigger(zero, min[i-1])) {
					mul(max[i], min[i-1], data[i]);
					mul(min[i], max[i-1], data[i]);
				}else {
					mul(max[i], one, data[i]);
					mul(min[i], one, data[i]);
				}
			}
		}
		
		int index = 1;
		for (int i = 2; i < count; ++ i) {
			if (bigger(max[i], max[index])) {
				index = i;
			}
		}
		output(max[index]);
		
		count = 1;
	}
	
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值