滚动数组滚粗
snakes 洛谷传送门
这个题,(⊙o⊙)…,滚动数组坑死人……………………………………
首先设计状态,你容易想到的是,dp[i][j][k]表示前i组,用了j次,这次的网是k。 然后你发现会炸空间,emmmmm。
优化
引理:你改变的网的大小一定属于a集合。
证明:因为你选择网的时候,假如改变,有两种情况。
1与这个相同 显然成立
2.与这个不同,那么他一定大于后面的一些数,假如他在后面有相同的数,那么显然成立,假如说没有的话,那么他一定大于后面一段的数。那么你让他等于这一段的最大的数,可以证明,不会让答案变得更差,所以也一定成立。
**
综上所述,成立
所以你第三维就可以优化成400,代表用了a[k]
但是,还是会炸,为啥呢,因为你没用滚动数组。
你首先把没用滚动数组优化的写出来,然后,你发现改完之后,你就炸了。
所以剩下的,自己调吧,**哈哈哈哈哈哈哈哈哈哈啊哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈**
不要问我为什么开滚动数组,不然这就是你的下场~~
#include<bits/stdc++.h>
using namespace std;
const int maxn=401;
int a[maxn];
int dp[2][maxn][maxn];
int minn[maxn][maxn];
int m,n,k1,ans=INT_MAX;
bool nimazhal=0;
int main() {
memset(dp,63,sizeof(dp));
memset(minn,63,sizeof(minn));
cin>>n>>k1;
for(int i=1; i<=n; i++) scanf("%d",&a[i]);
for(int i=1; i<=n; i++) dp[0][0][i]=0;
for(int i=1; i<=n; i++)
for(int j=0; j<=k1; j++)
for(int k=1; k<=n; k++) {
if(a[k]>=a[i]) {
if(j>=1) {
dp[i&1][j][k]=min(dp[(i-1)&1][j][k]+a[k]-a[i],minn[(i-1)][j-1]+a[k]-a[i]);
} else if(j==0)dp[i&1][j][k]=dp[(i-1)&1][j][k]+a[k]-a[i];
} else if(a[k]<a[i])dp[i&1][j][k]=minn[0][0];//一定要加,因为你如果不选的话,他不是正无穷。之前处理过。不然,你就全wrong了
minn[i][j]=min(minn[i][j],dp[i&1][j][k]);
if(i==n&&j==k1)
ans=min(ans,dp[i&1][j][k]);
}
cout<<ans;
return 0;
}