luogu P1220 关路灯

比较好的一道题吧。。。。。转移方程有点长(是我太弱了。。)
嘛,,,记得第一次见到这个题是在初二。。。。的时候。。。然后当时就被这个题劝退了
。。。。结果现在看起来也挺简单的啊。。。。。。。。。
嘛,只要考虑 状态怎么设立,这题就可以解决了。。。。
发现 子问题在这里,相当于是之前关灯区间。。。。。继承过来。。。。那么不一定要把最后一次关灯的位置记录下来。。
可以尝试一下(类似与预支答案的操作)直接记录最后是在右段点结束还是左端点结束。。。。
然后就可以直接把答案算出来了。。。

#include<bits/stdc++.h>
#define MAXN 50
using namespace std;

int n,c,sum[MAXN+5],f[MAXN+5][MAXN+5][3],tot;

//预处理出求和函数

struct node{
	int dx,dy;
}light[MAXN+5];

bool cmp(node x,node y){
	return x.dx<y.dx;
}

void init(){
	cin>>n>>c;
	for(int i = 1 ; i <= n ; i++)cin>>light[i].dx>>light[i].dy;
	sort(light+1,light+1+n,cmp);
	for(int i = 1 ; i <= n ; i++)sum[i] = sum[i-1] + light[i].dy;
	memset(f,0x7f,sizeof(f));tot = sum[n];
	f[c][c][0] = f[c][c][1] = 0;
}

int cal(int l,int r){
	return tot - (sum[r] - sum[l - 1]);
}

int jl(int l,int r){
	return light[r].dx - light[l].dx;
}

void solve(){
	for(int len = 2 ; len <= n ; len++){
		for(int i = 1 ; i+len-1 <= n ;i++){
			int j = i+len-1;
			//在左边的转移
			f[i][j][0] = min(f[i][j][0] , f[i+1][j][0] + jl(i,i+1) * cal(i+1,j));//i+1 从左到左 转移前在i+1
			f[i][j][0] = min(f[i][j][0] , f[i+1][j][1] + jl(i,j) * cal(i+1,j));//i+1 从右到左 转移前在j
			f[i][j][0] = min(f[i][j][0] , f[i][j-1][0] + jl(i,j) * cal(i,j-1) + jl(i,j) * cal(i,j));//j-1 从左到右再到左 转移前在i
			f[i][j][0] = min(f[i][j][0] , f[i][j-1][1] + jl(j-1,j) * cal(i,j-1) + jl(i,j) * cal(i,j));//j-1 从右边去j然后再回到左 转移前在j-1
			//在右边的转移
			f[i][j][1] = min(f[i][j][1] , f[i+1][j][0] + jl(i,i+1) * cal(i+1,j) + jl(i,j) * cal(i,j));//转移前在i+1 现在要去i 然后再去j
			f[i][j][1] = min(f[i][j][1] , f[i+1][j][1] + jl(i,j) * cal(i+1,j) + jl(i,j) * cal(i,j));//转移前在j  ——》i——》j
			f[i][j][1] = min(f[i][j][1] , f[i][j-1][0] + jl(i,j) * cal(i,j-1));//转移前在i 现在去就j
			f[i][j][1] = min(f[i][j][1] , f[i][j-1][1] + jl(j-1,j) * cal(i,j-1));//转移前在j-1 然后要去j
		}
	}
	cout<<min(f[1][n][0] , f[1][n][1])<<endl;
}

int main(){
	init();
	solve();
}

dp式子好工整。。。。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值