P5424 [USACO19OPEN]Snakes 动态规划之滚动数组

滚动数组滚粗

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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值