DP练习 石子合并

又做了一遍这个题,感觉自己之前写得好烂,代码上以及文字上…重写一遍叭
洛谷·题目:石子合并

题目叙述:

在这里插入图片描述

简单的思路分析

1.为什么贪心不行动规行

动规行感觉不用不赘述了,相信大家一看就懂,在这里我就简单解释下为什么贪心不行。
乍看贪心是可以的,我们第一直觉的是,比如5个数叭,最后结果中,最大的数加了4次,第二大的数也加了4次,第三大的数加了3次,第四大的数加了2次,最小的数只加了1次…看到这大家是不是就发现问题了呢?怎么可能顺序如此的正常好凑巧,但这就是贪心成立的前提,我们的确可以保证最大的能够加4次,但之后的第二大第三大这些数字加的次数我们就不能保证了,所以这也就是贪心不成立的缘由

2.环形我们怎么处理?

众所周知我们数组是线性结构的,那对这题的环形我们怎么处理呢?循环链表?循环链表能用dp处理么?那显然是不行的!所以我们重写一遍数组,比如数组大小为4,元素为1,2,3,4,那我们就,数组大小变成8,就变成了12341234,就可以实现循环啦

下面附上代码:

#include<bits/stdc++.h>
#define ll long long
using namespace std;
ll a[205];
ll dpmax[205][205];
ll dpmin[205][205];
ll suma[205];
int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0);
	
	int n;
	cin >> n;
	for (int i = 1; i <= n; i++)
	{
		cin >> a[i];
		a[i + n] = a[i];
	}
	for (int i = 1; i <= 2 * n; i++)
		suma[i] = suma[i - 1] + a[i];
	for(int p=1;p<n;p++)
		for (int i = 1; i + p < 2 * n; i++)
		{
			int j = i + p;
			dpmin[i][j] = 1e9 + 7;
			for (int k = i; k < j; k++)
			{
				dpmax[i][j] = max(dpmax[i][j], dpmax[i][k] + dpmax[k + 1][j] + suma[j] - suma[i - 1]);
				dpmin[i][j] = min(dpmin[i][j], dpmin[i][k] + dpmin[k + 1][j] + suma[j] - suma[i - 1]);
			}
		}
	ll remin = 1e9 + 7;
	ll remax = 0;
	for (int i = 1; i <= n; i++)
	{
		remin = min(remin, dpmin[i][i + n - 1]);
		remax = max(remax, dpmax[i][i + n - 1]);
	}
	cout << remin << endl << remax;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值