洛谷P1880 石子合并【区间型动态规划】
发布时间:2021年12月06日 20:12:12
发布人:jqh?
**题目描述**
在一个圆形操场的四周摆放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
```cpp
#include <iostream>
#include <cstdio>
#include <string.h>
#include <memory.h>
#include <queue>
#include <stack>
#include <cmath>
using namespace std;
int main()
{
int t,num[101],dpMin[100][100],dpMax[100][100]={{0}},n;//dp数组下标分别表示区间起始点和长度
cin>>n;
for(int i=0;i<n;++i)
for(int j=0;j<n;++j)
dpMin[i][j]=0x7fffffff;
num[0]=0;
for(int i=0; i<n; ++i)
{
cin>>t;
num[i+1]=num[i]+t;
dpMin[i][0]=0;
}
int score;
for(int len=1; len<n; ++len)
for(int i=0; i<n; ++i)
{
if(i+len>=n)
score=num[n]-num[i]+num[(i+len)%n+1];
else
score=num[i+len+1]-num[i];
for(int k=0; k<len; ++k)
{
dpMin[i][len]=min(dpMin[i][len],dpMin[i][k]+dpMin[(i+k+1)%n][len-k-1]+score);
dpMax[i][len]=max(dpMax[i][len],dpMax[i][k]+dpMax[(i+k+1)%n][len-k-1]+score);
}
}
int ansMin=0x7fffffff,ansMax=0;
for(int i=0;i<n;++i)
{
ansMin=min(ansMin,dpMin[i][n-1]);
ansMax=max(ansMax,dpMax[i][n-1]);
}
cout<<ansMin<<endl<<ansMax;
return 0;
}
```
热门评论: