又做了一遍这个题,感觉自己之前写得好烂,代码上以及文字上…重写一遍叭
洛谷·题目:石子合并
题目叙述:
简单的思路分析
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;
}