题目
合并石子 https://www.luogu.org/problem/show?pid=1880
题目描述
在一个园形操场的四周摆放N堆石子,现要将石子有次序地合并成一堆.规定每次只能选相邻的2堆合并成新的一堆,并将新的一堆的石子数,记为该次合并的得分。
试设计出1个算法,计算出将N堆石子合并成1堆的最小得分和最大得分.
输入输出格式
输入格式:
数据的第1行试正整数N,1≤N≤100,表示有N堆石子.第2行有N个数,分别表示每堆石子的个数.
输出格式:
输出共2行,第1行为最小得分,第2行为最大得分.
输入输出样例
输入样例#1:
4
4 5 9 4
输出样例#1:
43
54
思路
不难理解我们可以想象一个圆环的数据结构,但是圆环这样的结构太难处理,我们可以将它线性化。首先第一步就是破环为线。
4 5 9 4
扩充成 4 5 9 4 4 5 9 ,规定每次遍历的长度只能是4个。
我们写个dfs(l,r)函数,返回l到r之间的最小得分。
在主函数里面 我们dfs(0,3) dfs(1,4) dfs(2,5)…等等
最后寻找上面中最小的值时多少 就是我们呢要求得最小得分。
代码
#include<list>
#include<vector>
#include<math.h>
#include<iostream>
#include<algorithm>
using namespace std;
#define MAXSIZE 15001
#define INF 0xff
int N = 0;
int minAns = 0xffff;
int maxAns = 0;
std::vector<int> inputVector;
int dpDfs[INF][INF] = { 0 };
int dpDfs2[INF][INF] = { 0 };
int dfs(int l, int r);
int sum(int l, int r);
// return : [l,r]区间内最小的得分
int dfs(int l,int r)
{
if (dpDfs[l][r] != 0)
{
return dpDfs[l][r];
}
if (l == r)
{
return 0;
}
if (l + 1 == r)
{
return inputVector[l] + inputVector[r];
}
int LocMinAns = 0xffff;
for (int ti = l; ti < r; ++ti)
{
int temp = 0;
temp = dfs(l, ti) + dfs(ti + 1, r) + sum(l, r);
LocMinAns = min(LocMinAns, temp);
}
dpDfs[l][r] = LocMinAns;
return LocMinAns;
}
// 求区间最大值
int dfs2(int l, int r)
{
if (dpDfs2[l][r] != 0)
{
return dpDfs2[l][r];
}
if (l == r)
{
return 0;
}
if (l + 1 == r)
{
return inputVector[l] + inputVector[r];
}
int LocMaxAns = 0;
for (int ti = l; ti < r; ++ti)
{
int temp = 0;
temp = dfs2(l, ti) + dfs2(ti + 1, r) + sum(l, r);
LocMaxAns = max(LocMaxAns, temp);
}
dpDfs2[l][r] = LocMaxAns;
return LocMaxAns;
}
int sum(int l, int r)
{
int sumAns = 0;
for (int i = l; i <= r; ++i)
{
sumAns += inputVector[i];
}
return sumAns;
}
int main()
{
cin >> N;
// 读入N个数据
while (N--)
{
int temp = 0;
cin >> temp;
inputVector.push_back(temp);
}
int size = 0;
size = inputVector.size();
// 1 2 3 4 5 4 3 2 1 如此扩充n-1个数字
for (int i = 0; i<size-1; ++i)
{
inputVector.push_back(inputVector[i]);
}
for (int l = 0; l < inputVector.size()/2; l++)
{
int temp = 0;
int r = l + inputVector.size() / 2;
temp = dfs(l, r);
minAns = min(temp, minAns);
temp = 0;
temp = dfs2(l, r);
maxAns = max(temp, maxAns);
}
cout << minAns<<endl;
cout << maxAns;
return 0;
}

3821

被折叠的 条评论
为什么被折叠?



