BZOJ 1694 && 2037 【DP……算是区间?

本文提供BZOJ1694和2037两道题目的详细解答过程,通过动态规划算法解决区间端点问题,包括代码实现和关键步骤说明。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

先送个大爷的题解传送门


显然在经过了l点和r点之后,[l,r]中途的点也是经过了的,并不会有任何贡献,于是可以用f[l][r]来记录这一段的贡献,还要记录当前是在左端点还是右端点,于是再开一维0..1就好了

每次转移到 l-1和r+1,转移的代价就是当前未经过的点在转移的时间里减少的价值。

BZOJ 1694直接用数量就好,2037开个前缀和瞎搞搞就好


注意给出的数据是无序的


1694:

#include<bits/stdc++.h>
#define MAXN 1005
#define INF 0x3f3f3f3f
using namespace std;	int n,l;
int p[MAXN];
int f[MAXN][MAXN][2];

int main(){
	scanf("%d%d",&n,&l);
	for(int i=1;i<=n;++i)	scanf("%d",p+i);
	sort(p+1,p+n+1);	
	memset(f,INF,sizeof f);
	for(int i=1;i<=n;++i)	f[i][i][0] = f[i][i][1] = abs(l-p[i])*n;
	for(int i=2;i<=n;++i){
		for(int l=1,r=i;r<=n;++l,++r){
			f[l][r][0] = min(f[l+1][r][0] + (p[l+1]-p[l]) * (n-i+1),
							 f[l+1][r][1] + (p[r]-p[l]) * (n-i+1));
			f[l][r][1] = min(f[l][r-1][0] + (p[r]-p[l]) * (n-i+1),
							 f[l][r-1][1] + (p[r]-p[r-1]) * (n-i+1));
		}
	}
	printf("%d",min(f[1][n][0],f[1][n][1]));
	return 0;
}

2037:

#include<bits/stdc++.h>
#define MAXN 1005
using namespace std;	int n,x0;
struct t1{
	int x,v;
	bool operator < (const t1 &ano) const{
		return x<ano.x;
	}
}dt[MAXN];
int a[MAXN],b;
int f[MAXN][MAXN][2];
int sum[MAXN];
int ans = 0;

int main(){
//	freopen("1.in","r",stdin);
	scanf("%d%d",&n,&x0);
	for(int i=1;i<=n;++i)	scanf("%d",&dt[i].x);
	for(int i=1;i<=n;++i)	scanf("%d",&b) , ans += b;
	for(int i=1;i<=n;++i)	scanf("%d",&dt[i].v);
	
	sort(dt+1,dt+n+1);
	for(int i=1;i<=n;++i)	a[i] = dt[i].x;
	for(int i=1;i<=n;++i)	sum[i] = sum[i-1] + dt[i].v;
	for(int i=1;i<=n;++i)	f[i][i][0] = f[i][i][1] = abs(x0 - a[i]) * sum[n];
	for(int i=2;i<=n;++i)
		for(int l=1,r=i;r<=n;++l,++r){
			f[l][r][0] = min( f[l+1][r][0] + (a[l+1] - a[l]) * (sum[n] - sum[r] + sum[l]),
							  f[l+1][r][1] + (a[r] - a[l]) * (sum[n] - sum[r] + sum[l]));
			f[l][r][1] = min( f[l][r-1][0] + (a[r] - a[l]) * (sum[n] - sum[r-1] + sum[l-1]),
							  f[l][r-1][1] + (a[r] - a[r-1]) * (sum[n] - sum[r-1] + sum[l-1]));
		}
	
	printf("%.3f",(double)(ans - min(f[1][n][0],f[1][n][1]))/1000);
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值