
稍微讲一下思路
先按照大小排序,这明显跟顺序没关系。
而后如果我们已经有了两个点了,现在要把第三个点加进去
如果加到中间的花,发现当前最大最小值没有改变。加到哦湖面发现最大值改变了,如果加到中间我们考虑可以
先加入左边第一个圆点,再加第一个三角,再加第二个圆点
比
现价左边第一个圆点,再加第二个圆点,再加中间的三角肯定来的更优。
那么意味着我们是不是每次都要选择一个临近的点加入而不能采取插入的形式。
最后再考虑 1 4 8 10 14
这肯定线加入8和10 而后考虑到4和14的距离都是4,但是4左边有一个1
发现 8 10 4 1 14的顺序比8 10 14 4 1的情况更优。
那么就是说我们在每个区间的时候都要决策左边和右边加哪个更优,这显然在每个局部都会出现这样的问题,这就说明这是一道区间DP的题目了。
显然那我们现在考虑
dp[i][j]dp[i][j]dp[i][j]表示我们的从第iii到第jjj区间内的ansansans
那么我们这个状态的前一个状态肯定是考虑加入a[i]a[i]a[i]或者a[j]a[j]a[j]得到的。
考虑转移式子
dp[i][j]=a[j]−a[i]+min(dp[i+1][j],dp[i][j−1])dp[i][j]=a[j]-a[i]+min(dp[i+1][j],dp[i][j-1])dp[i][j]=a[j]−a[i]+min(dp[i+1][j],dp[i][j−1])
在考虑需不需要手动定义边界情况。考虑我们这里的边界情况就是i=ji=ji=j的情况这是ans=0ans=0ans=0我们初始化就是0不需要手动定义。
下边给代码:
//acmer mxc
#include<bits/stdc++.h>
#define mst(s,x) memset(s,x,sizeof(s));
#define sr(x) scanf("%lld",&x);
#define sr2(a,b) scanf("%d%d",&a,&b);
#define sr3(a,b,c) scanf("%d%d%d",&a,&b,&c);
#define f(i,a,n) for(int i=a;i<=n;i++)
#define sc(x) cout<<#x<<" : "<<x<<endl;
#define hh cout<<endl;
#define pii pair<int,int>
#define pb(x) push_back(x)
#define mk(a,b) make_pair(a,b)
#define ls(x) x<<1
#define rs(x) x<<1|1
#define fi first
#define se second
#define inf 0x3f3f3f3f
#define ll __int128
using namespace std;
inline ll read()
{
ll x=0,w=1; char c=getchar();
while(c<'0'||c>'9') {if(c=='-') w=-1; c=getchar();}
while(c<='9'&&c>='0') x=(x<<1)+(x<<3)+c-'0',c=getchar();
return w==1?x:-x;
}
inline void write(ll x)
{
if(x>=10) write(x/10);
putchar(x%10+'0');
}
//------------------------------------------------
// #define int __int128
#define int long long
#define LL long long
#define dd double
const int N=2e3+5;
int n;
int a[N];
int dp[N][N];
inline void solve()
{
scanf("%lld",&n);
for(int i=1;i<=n;i++)
{
scanf("%lld",&a[i]);
}
sort(a+1,a+1+n);
for(int len=2;len<=n;len++)
{
for(int i=1;i<=n;i++)
{
int j=i+len-1;
if(j>n) break;
dp[i][j]=a[j]-a[i]+min(dp[i+1][j],dp[i][j-1]);
}
}
printf("%lld",dp[1][n]);
return;
}
//------------------------------------------------
signed main()
{
clock_t c1=clock();
#ifdef LOCAL
freopen("in.in","r",stdin);
freopen("out.out","w",stdout);
#endif
//==================================
int T=1;
// cin>>T;
for(int i=1;i<=T;i++)
{
solve();
}
//==================================
end:
cerr<< endl << "Time used:" << clock() - c1 << endl;
return 0;
}
该博客讨论了一种区间动态规划问题,通过分析如何在给定序列中加入元素以保持最大最小值差的最小,揭示了使用区间DP的方法求解。重点在于理解转移方程和决策过程,以及如何应用到实际代码中。

1460

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



